2005-07-07 00:41:33 +04:00
/*
* runtest . c : C program to run libxml2 regression tests without
2019-09-30 18:04:54 +03:00
* requiring make or Python , and reducing platform dependencies
2005-07-07 00:41:33 +04:00
* to a strict minimum .
*
* To compile on Unixes :
* cc - o runtest ` xml2 - config - - cflags ` runtest . c ` xml2 - config - - libs ` - lpthread
*
* See Copyright for the status of this software .
*
* daniel @ veillard . com
*/
2024-05-02 17:23:04 +03:00
# define XML_DEPRECATED
2024-06-11 00:06:13 +03:00
# define XML_DEPRECATED_MEMBER
2024-05-02 17:23:04 +03:00
2023-11-18 16:36:41 +03:00
# include "libxml.h"
2005-10-28 20:37:05 +04:00
# include <stdio.h>
2022-11-22 17:40:51 +03:00
# ifdef HAVE_UNISTD_H
2005-07-07 00:41:33 +04:00
# include <unistd.h>
2022-11-22 17:40:51 +03:00
# elif defined (_WIN32)
# include <io.h>
2005-07-07 00:41:33 +04:00
# endif
2023-09-21 01:44:50 +03:00
# include <stdlib.h>
2005-07-07 00:41:33 +04:00
# include <string.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <libxml/parser.h>
2017-06-16 22:38:57 +03:00
# include <libxml/parserInternals.h>
2005-07-07 00:41:33 +04:00
# include <libxml/tree.h>
# include <libxml/uri.h>
2017-10-31 19:17:16 +03:00
# include <libxml/encoding.h>
2005-07-07 00:41:33 +04:00
# ifdef LIBXML_OUTPUT_ENABLED
# ifdef LIBXML_READER_ENABLED
# include <libxml/xmlreader.h>
# endif
# ifdef LIBXML_XINCLUDE_ENABLED
# include <libxml/xinclude.h>
# endif
# ifdef LIBXML_XPATH_ENABLED
# include <libxml/xpath.h>
# include <libxml/xpathInternals.h>
# ifdef LIBXML_XPTR_ENABLED
# include <libxml/xpointer.h>
# endif
# endif
# ifdef LIBXML_SCHEMAS_ENABLED
# include <libxml/relaxng.h>
# include <libxml/xmlschemas.h>
# include <libxml/xmlschemastypes.h>
# endif
# ifdef LIBXML_PATTERN_ENABLED
# include <libxml/pattern.h>
# endif
# ifdef LIBXML_C14N_ENABLED
# include <libxml/c14n.h>
# endif
# ifdef LIBXML_HTML_ENABLED
# include <libxml/HTMLparser.h>
# include <libxml/HTMLtree.h>
# endif
# if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
# include <libxml/threads.h>
# include <libxml/parser.h>
2024-06-16 02:20:04 +03:00
# endif
# ifdef LIBXML_CATALOG_ENABLED
2005-07-07 00:41:33 +04:00
# include <libxml/catalog.h>
# endif
2023-05-24 21:08:33 +03:00
/*
* pseudo flag for the unification of HTML and XML tests
*/
# define XML_PARSE_HTML 1 << 24
2005-07-07 00:41:33 +04:00
/*
* O_BINARY is just for Windows compatibility - if it isn ' t defined
* on this system , avoid any compilation error
*/
# ifdef O_BINARY
# define RD_FLAGS O_RDONLY | O_BINARY
2016-05-22 04:58:30 +03:00
# define WR_FLAGS O_WRONLY | O_CREAT | O_TRUNC | O_BINARY
2005-07-07 00:41:33 +04:00
# else
2016-05-22 04:58:30 +03:00
# define RD_FLAGS O_RDONLY
# define WR_FLAGS O_WRONLY | O_CREAT | O_TRUNC
2005-07-07 00:41:33 +04:00
# endif
typedef int ( * functest ) ( const char * filename , const char * result ,
const char * error , int options ) ;
typedef struct testDesc testDesc ;
typedef testDesc * testDescPtr ;
struct testDesc {
2019-09-30 18:04:54 +03:00
const char * desc ; /* description of the test */
2005-07-07 00:41:33 +04:00
functest func ; /* function implementing the test */
const char * in ; /* glob to path for input files */
const char * out ; /* output directory */
const char * suffix ; /* suffix for output files */
const char * err ; /* suffix for error output files */
int options ; /* parser options for the test */
} ;
2016-05-22 04:58:30 +03:00
static int update_results = 0 ;
2020-06-04 12:58:04 +03:00
static char * temp_directory = NULL ;
2005-07-07 00:41:33 +04:00
static int checkTestFile ( const char * filename ) ;
2022-03-01 00:42:10 +03:00
# if defined(_WIN32)
2005-07-07 00:41:33 +04:00
# include <windows.h>
typedef struct
{
size_t gl_pathc ; /* Count of paths matched so far */
char * * gl_pathv ; /* List of matched pathnames. */
size_t gl_offs ; /* Slots to reserve in 'gl_pathv'. */
} glob_t ;
# define GLOB_DOOFFS 0
2017-10-09 03:05:41 +03:00
static int glob ( const char * pattern , ATTRIBUTE_UNUSED int flags ,
ATTRIBUTE_UNUSED int errfunc ( const char * epath , int eerrno ) ,
2005-07-07 00:41:33 +04:00
glob_t * pglob ) {
glob_t * ret ;
WIN32_FIND_DATA FindFileData ;
HANDLE hFind ;
unsigned int nb_paths = 0 ;
char directory [ 500 ] ;
int len ;
if ( ( pattern = = NULL ) | | ( pglob = = NULL ) ) return ( - 1 ) ;
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
strncpy ( directory , pattern , 499 ) ;
for ( len = strlen ( directory ) ; len > = 0 ; len - - ) {
if ( directory [ len ] = = ' / ' ) {
len + + ;
directory [ len ] = 0 ;
break ;
}
}
if ( len < = 0 )
len = 0 ;
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
ret = pglob ;
memset ( ret , 0 , sizeof ( glob_t ) ) ;
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
hFind = FindFirstFileA ( pattern , & FindFileData ) ;
2008-08-25 18:53:31 +04:00
if ( hFind = = INVALID_HANDLE_VALUE )
2005-07-07 00:41:33 +04:00
return ( 0 ) ;
nb_paths = 20 ;
ret - > gl_pathv = ( char * * ) malloc ( nb_paths * sizeof ( char * ) ) ;
if ( ret - > gl_pathv = = NULL ) {
FindClose ( hFind ) ;
return ( - 1 ) ;
}
strncpy ( directory + len , FindFileData . cFileName , 499 - len ) ;
ret - > gl_pathv [ ret - > gl_pathc ] = strdup ( directory ) ;
if ( ret - > gl_pathv [ ret - > gl_pathc ] = = NULL )
goto done ;
ret - > gl_pathc + + ;
while ( FindNextFileA ( hFind , & FindFileData ) ) {
if ( FindFileData . cFileName [ 0 ] = = ' . ' )
continue ;
if ( ret - > gl_pathc + 2 > nb_paths ) {
char * * tmp = realloc ( ret - > gl_pathv , nb_paths * 2 * sizeof ( char * ) ) ;
if ( tmp = = NULL )
break ;
ret - > gl_pathv = tmp ;
nb_paths * = 2 ;
}
strncpy ( directory + len , FindFileData . cFileName , 499 - len ) ;
ret - > gl_pathv [ ret - > gl_pathc ] = strdup ( directory ) ;
if ( ret - > gl_pathv [ ret - > gl_pathc ] = = NULL )
break ;
ret - > gl_pathc + + ;
}
ret - > gl_pathv [ ret - > gl_pathc ] = NULL ;
done :
FindClose ( hFind ) ;
return ( 0 ) ;
}
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
static void globfree ( glob_t * pglob ) {
unsigned int i ;
if ( pglob = = NULL )
return ;
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
for ( i = 0 ; i < pglob - > gl_pathc ; i + + ) {
if ( pglob - > gl_pathv [ i ] ! = NULL )
free ( pglob - > gl_pathv [ i ] ) ;
}
}
2012-05-23 11:52:45 +04:00
2005-07-07 00:41:33 +04:00
# else
# include <glob.h>
# endif
/************************************************************************
* *
* Libxml2 specific routines *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int nb_tests = 0 ;
static int nb_errors = 0 ;
static int nb_leaks = 0 ;
static int
fatalError ( void ) {
fprintf ( stderr , " Exitting tests on fatal error \n " ) ;
exit ( 1 ) ;
}
/*
* Trapping the error messages at the generic level to grab the equivalent of
* stderr messages on CLI tools .
*/
static char testErrors [ 32769 ] ;
static int testErrorsSize = 0 ;
2022-12-08 04:43:17 +03:00
static void
2005-07-07 00:41:33 +04:00
testErrorHandler ( void * ctx ATTRIBUTE_UNUSED , const char * msg , . . . ) {
va_list args ;
int res ;
if ( testErrorsSize > = 32768 )
return ;
va_start ( args , msg ) ;
res = vsnprintf ( & testErrors [ testErrorsSize ] ,
32768 - testErrorsSize ,
msg , args ) ;
va_end ( args ) ;
if ( testErrorsSize + res > = 32768 ) {
/* buffer is full */
testErrorsSize = 32768 ;
testErrors [ testErrorsSize ] = 0 ;
} else {
testErrorsSize + = res ;
}
testErrors [ testErrorsSize ] = 0 ;
}
static void
2023-10-24 16:02:36 +03:00
testStructuredErrorHandler ( void * ctx ATTRIBUTE_UNUSED , const xmlError * err ) {
2024-01-04 04:48:02 +03:00
xmlFormatError ( err , testErrorHandler , NULL ) ;
2005-07-07 00:41:33 +04:00
}
static void
initializeLibxml2 ( void ) {
2022-11-25 16:15:43 +03:00
/*
* This verifies that xmlInitParser doesn ' t allocate memory with
* xmlMalloc
*/
xmlFree = NULL ;
xmlMalloc = NULL ;
xmlRealloc = NULL ;
xmlMemStrdup = NULL ;
2005-07-07 00:41:33 +04:00
xmlInitParser ( ) ;
2022-11-25 16:15:43 +03:00
xmlMemSetup ( xmlMemFree , xmlMemMalloc , xmlMemRealloc , xmlMemoryStrdup ) ;
2024-06-11 12:34:48 +03:00
# ifdef LIBXML_CATALOG_ENABLED
2024-06-15 20:37:27 +03:00
/*
* Disable system catalog which could cause lazy memory allocations
* resulting in false positive memory leaks .
*/
2024-06-11 12:34:48 +03:00
# ifdef _WIN32
putenv ( " XML_CATALOG_FILES= " ) ;
# else
setenv ( " XML_CATALOG_FILES " , " " , 1 ) ;
# endif
xmlInitializeCatalog ( ) ;
# endif
2005-07-07 00:41:33 +04:00
# ifdef LIBXML_SCHEMAS_ENABLED
xmlSchemaInitTypes ( ) ;
xmlRelaxNGInitTypes ( ) ;
# endif
}
/************************************************************************
* *
* File name and path utilities *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static const char * baseFilename ( const char * filename ) {
const char * cur ;
if ( filename = = NULL )
return ( NULL ) ;
cur = & filename [ strlen ( filename ) ] ;
while ( ( cur > filename ) & & ( * cur ! = ' / ' ) )
cur - - ;
if ( * cur = = ' / ' )
return ( cur + 1 ) ;
return ( cur ) ;
}
static char * resultFilename ( const char * filename , const char * out ,
const char * suffix ) {
const char * base ;
char res [ 500 ] ;
2006-06-18 21:31:31 +04:00
char suffixbuff [ 500 ] ;
2005-07-07 00:41:33 +04:00
/*************
if ( ( filename [ 0 ] = = ' t ' ) & & ( filename [ 1 ] = = ' e ' ) & &
( filename [ 2 ] = = ' s ' ) & & ( filename [ 3 ] = = ' t ' ) & &
( filename [ 4 ] = = ' / ' ) )
filename = & filename [ 5 ] ;
* * * * * * * * * * * * */
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
base = baseFilename ( filename ) ;
if ( suffix = = NULL )
suffix = " .tmp " ;
if ( out = = NULL )
out = " " ;
2006-06-18 21:31:31 +04:00
strncpy ( suffixbuff , suffix , 499 ) ;
2019-01-01 18:30:38 +03:00
if ( snprintf ( res , 499 , " %s%s%s " , out , base , suffixbuff ) > = 499 )
res [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
return ( strdup ( res ) ) ;
}
static int checkTestFile ( const char * filename ) {
struct stat buf ;
if ( stat ( filename , & buf ) = = - 1 )
return ( 0 ) ;
2022-03-01 00:42:10 +03:00
# if defined(_WIN32)
2005-07-07 00:41:33 +04:00
if ( ! ( buf . st_mode & _S_IFREG ) )
return ( 0 ) ;
# else
if ( ! S_ISREG ( buf . st_mode ) )
return ( 0 ) ;
# endif
return ( 1 ) ;
}
2016-05-22 04:58:30 +03:00
static int compareFiles ( const char * r1 /* temp */ , const char * r2 /* result */ ) {
2020-07-09 04:19:13 +03:00
int res1 , res2 , total ;
2005-07-07 00:41:33 +04:00
int fd1 , fd2 ;
char bytes1 [ 4096 ] ;
char bytes2 [ 4096 ] ;
2016-05-22 04:58:30 +03:00
if ( update_results ) {
fd1 = open ( r1 , RD_FLAGS ) ;
if ( fd1 < 0 )
return ( - 1 ) ;
fd2 = open ( r2 , WR_FLAGS , 0644 ) ;
if ( fd2 < 0 ) {
close ( fd1 ) ;
return ( - 1 ) ;
}
2020-07-09 04:19:13 +03:00
total = 0 ;
2016-05-22 04:58:30 +03:00
do {
res1 = read ( fd1 , bytes1 , 4096 ) ;
if ( res1 < = 0 )
break ;
2020-07-09 04:19:13 +03:00
total + = res1 ;
2016-05-22 04:58:30 +03:00
res2 = write ( fd2 , bytes1 , res1 ) ;
if ( res2 < = 0 | | res2 ! = res1 )
break ;
} while ( 1 ) ;
close ( fd2 ) ;
close ( fd1 ) ;
2020-07-09 04:19:13 +03:00
if ( total = = 0 )
unlink ( r2 ) ;
2016-05-22 04:58:30 +03:00
return ( res1 ! = 0 ) ;
}
2005-07-07 00:41:33 +04:00
fd1 = open ( r1 , RD_FLAGS ) ;
if ( fd1 < 0 )
return ( - 1 ) ;
fd2 = open ( r2 , RD_FLAGS ) ;
while ( 1 ) {
res1 = read ( fd1 , bytes1 , 4096 ) ;
2020-07-09 04:19:13 +03:00
res2 = fd2 > = 0 ? read ( fd2 , bytes2 , 4096 ) : 0 ;
2006-03-10 03:36:23 +03:00
if ( ( res1 ! = res2 ) | | ( res1 < 0 ) ) {
2005-07-07 00:41:33 +04:00
close ( fd1 ) ;
2020-07-09 04:19:13 +03:00
if ( fd2 > = 0 )
close ( fd2 ) ;
2005-07-07 00:41:33 +04:00
return ( 1 ) ;
}
if ( res1 = = 0 )
break ;
if ( memcmp ( bytes1 , bytes2 , res1 ) ! = 0 ) {
close ( fd1 ) ;
2020-07-09 04:19:13 +03:00
if ( fd2 > = 0 )
close ( fd2 ) ;
2005-07-07 00:41:33 +04:00
return ( 1 ) ;
}
}
close ( fd1 ) ;
2020-07-09 04:19:13 +03:00
if ( fd2 > = 0 )
close ( fd2 ) ;
2005-07-07 00:41:33 +04:00
return ( 0 ) ;
}
static int compareFileMem ( const char * filename , const char * mem , int size ) {
int res ;
int fd ;
char bytes [ 4096 ] ;
int idx = 0 ;
struct stat info ;
2016-05-22 04:58:30 +03:00
if ( update_results ) {
2020-07-09 04:19:13 +03:00
if ( size = = 0 ) {
unlink ( filename ) ;
return ( 0 ) ;
}
2016-05-22 04:58:30 +03:00
fd = open ( filename , WR_FLAGS , 0644 ) ;
2016-05-22 06:14:45 +03:00
if ( fd < 0 ) {
fprintf ( stderr , " failed to open %s for writing " , filename ) ;
2016-05-22 04:58:30 +03:00
return ( - 1 ) ;
2016-05-22 06:14:45 +03:00
}
2016-05-22 04:58:30 +03:00
res = write ( fd , mem , size ) ;
close ( fd ) ;
return ( res ! = size ) ;
}
2016-05-22 06:14:45 +03:00
if ( stat ( filename , & info ) < 0 ) {
2020-07-09 04:19:13 +03:00
if ( size = = 0 )
return ( 0 ) ;
2016-05-22 06:14:45 +03:00
fprintf ( stderr , " failed to stat %s \n " , filename ) ;
2005-07-07 00:41:33 +04:00
return ( - 1 ) ;
2016-05-22 06:14:45 +03:00
}
if ( info . st_size ! = size ) {
fprintf ( stderr , " file %s is %ld bytes, result is %d bytes \n " ,
2016-08-22 12:44:18 +03:00
filename , ( long ) info . st_size , size ) ;
2005-07-07 00:41:33 +04:00
return ( - 1 ) ;
2016-05-22 06:14:45 +03:00
}
2005-07-07 00:41:33 +04:00
fd = open ( filename , RD_FLAGS ) ;
2016-05-22 06:14:45 +03:00
if ( fd < 0 ) {
fprintf ( stderr , " failed to open %s for reading " , filename ) ;
2005-07-07 00:41:33 +04:00
return ( - 1 ) ;
2016-05-22 06:14:45 +03:00
}
2005-07-07 00:41:33 +04:00
while ( idx < size ) {
res = read ( fd , bytes , 4096 ) ;
if ( res < = 0 )
break ;
2008-08-25 18:53:31 +04:00
if ( res + idx > size )
2005-07-07 00:41:33 +04:00
break ;
if ( memcmp ( bytes , & mem [ idx ] , res ) ! = 0 ) {
int ix ;
for ( ix = 0 ; ix < res ; ix + + )
if ( bytes [ ix ] ! = mem [ idx + ix ] )
break ;
fprintf ( stderr , " Compare error at position %d \n " , idx + ix ) ;
close ( fd ) ;
return ( 1 ) ;
}
idx + = res ;
}
close ( fd ) ;
2016-05-22 06:14:45 +03:00
if ( idx ! = size ) {
fprintf ( stderr , " Compare error index %d, size %d \n " , idx , size ) ;
}
2005-07-07 00:41:33 +04:00
return ( idx ! = size ) ;
}
static int loadMem ( const char * filename , const char * * mem , int * size ) {
int fd , res ;
struct stat info ;
char * base ;
int siz = 0 ;
2008-08-25 18:53:31 +04:00
if ( stat ( filename , & info ) < 0 )
2005-07-07 00:41:33 +04:00
return ( - 1 ) ;
base = malloc ( info . st_size + 1 ) ;
if ( base = = NULL )
return ( - 1 ) ;
if ( ( fd = open ( filename , RD_FLAGS ) ) < 0 ) {
free ( base ) ;
return ( - 1 ) ;
}
while ( ( res = read ( fd , & base [ siz ] , info . st_size - siz ) ) > 0 ) {
siz + = res ;
}
close ( fd ) ;
# if !defined(_WIN32)
if ( siz ! = info . st_size ) {
free ( base ) ;
return ( - 1 ) ;
}
# endif
base [ siz ] = 0 ;
* mem = base ;
* size = siz ;
return ( 0 ) ;
}
static int unloadMem ( const char * mem ) {
free ( ( char * ) mem ) ;
return ( 0 ) ;
}
/************************************************************************
* *
* Tests implementations *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/************************************************************************
* *
* Parse to SAX based tests *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-07-29 03:49:35 +04:00
static FILE * SAXdebug = NULL ;
2005-07-07 00:41:33 +04:00
/*
* empty SAX block
*/
2005-07-29 03:49:35 +04:00
static xmlSAXHandler emptySAXHandlerStruct = {
2005-07-07 00:41:33 +04:00
NULL , /* internalSubset */
NULL , /* isStandalone */
NULL , /* hasInternalSubset */
NULL , /* hasExternalSubset */
NULL , /* resolveEntity */
NULL , /* getEntity */
NULL , /* entityDecl */
NULL , /* notationDecl */
NULL , /* attributeDecl */
NULL , /* elementDecl */
NULL , /* unparsedEntityDecl */
NULL , /* setDocumentLocator */
NULL , /* startDocument */
NULL , /* endDocument */
NULL , /* startElement */
NULL , /* endElement */
NULL , /* reference */
NULL , /* characters */
NULL , /* ignorableWhitespace */
NULL , /* processingInstruction */
NULL , /* comment */
NULL , /* xmlParserWarning */
NULL , /* xmlParserError */
NULL , /* xmlParserError */
NULL , /* getParameterEntity */
NULL , /* cdataBlock; */
NULL , /* externalSubset; */
1 ,
NULL ,
NULL , /* startElementNs */
NULL , /* endElementNs */
NULL /* xmlStructuredErrorFunc */
} ;
2023-10-06 11:44:38 +03:00
typedef struct {
const char * filename ;
xmlHashTablePtr generalEntities ;
xmlHashTablePtr parameterEntities ;
} debugContext ;
2005-07-07 00:41:33 +04:00
static xmlSAXHandlerPtr emptySAXHandler = & emptySAXHandlerStruct ;
2005-07-29 03:49:35 +04:00
static int callbacks = 0 ;
static int quiet = 0 ;
2005-07-07 00:41:33 +04:00
/**
* isStandaloneDebug :
* @ ctxt : An XML parser context
*
* Is this document tagged standalone ?
*
* Returns 1 if true
*/
static int
isStandaloneDebug ( void * ctx ATTRIBUTE_UNUSED )
{
callbacks + + ;
if ( quiet )
return ( 0 ) ;
fprintf ( SAXdebug , " SAX.isStandalone() \n " ) ;
return ( 0 ) ;
}
/**
* hasInternalSubsetDebug :
* @ ctxt : An XML parser context
*
* Does this document has an internal subset
*
* Returns 1 if true
*/
static int
hasInternalSubsetDebug ( void * ctx ATTRIBUTE_UNUSED )
{
callbacks + + ;
if ( quiet )
return ( 0 ) ;
fprintf ( SAXdebug , " SAX.hasInternalSubset() \n " ) ;
return ( 0 ) ;
}
/**
* hasExternalSubsetDebug :
* @ ctxt : An XML parser context
*
* Does this document has an external subset
*
* Returns 1 if true
*/
static int
hasExternalSubsetDebug ( void * ctx ATTRIBUTE_UNUSED )
{
callbacks + + ;
if ( quiet )
return ( 0 ) ;
fprintf ( SAXdebug , " SAX.hasExternalSubset() \n " ) ;
return ( 0 ) ;
}
/**
* internalSubsetDebug :
* @ ctxt : An XML parser context
*
* Does this document has an internal subset
*/
static void
internalSubsetDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * name ,
const xmlChar * ExternalID , const xmlChar * SystemID )
{
callbacks + + ;
if ( quiet )
return ;
2019-08-01 16:01:47 +03:00
if ( name = = NULL )
name = BAD_CAST " (null) " ;
2005-07-07 00:41:33 +04:00
fprintf ( SAXdebug , " SAX.internalSubset(%s, " , name ) ;
if ( ExternalID = = NULL )
fprintf ( SAXdebug , " , " ) ;
else
fprintf ( SAXdebug , " %s, " , ExternalID ) ;
if ( SystemID = = NULL )
fprintf ( SAXdebug , " ) \n " ) ;
else
fprintf ( SAXdebug , " %s) \n " , SystemID ) ;
}
/**
* externalSubsetDebug :
* @ ctxt : An XML parser context
*
* Does this document has an external subset
*/
static void
externalSubsetDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * name ,
const xmlChar * ExternalID , const xmlChar * SystemID )
{
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.externalSubset(%s, " , name ) ;
if ( ExternalID = = NULL )
fprintf ( SAXdebug , " , " ) ;
else
fprintf ( SAXdebug , " %s, " , ExternalID ) ;
if ( SystemID = = NULL )
fprintf ( SAXdebug , " ) \n " ) ;
else
fprintf ( SAXdebug , " %s) \n " , SystemID ) ;
}
/**
* resolveEntityDebug :
* @ ctxt : An XML parser context
* @ publicId : The public ID of the entity
* @ systemId : The system ID of the entity
*
* Special entity resolver , better left to the parser , it has
* more context than the application layer .
* The default behaviour is to NOT resolve the entities , in that case
* the ENTITY_REF nodes are built in the structure ( and the parameter
* values ) .
*
* Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour .
*/
static xmlParserInputPtr
resolveEntityDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * publicId , const xmlChar * systemId )
{
callbacks + + ;
if ( quiet )
return ( NULL ) ;
/* xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; */
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
fprintf ( SAXdebug , " SAX.resolveEntity( " ) ;
if ( publicId ! = NULL )
fprintf ( SAXdebug , " %s " , ( char * ) publicId ) ;
else
fprintf ( SAXdebug , " " ) ;
if ( systemId ! = NULL )
fprintf ( SAXdebug , " , %s) \n " , ( char * ) systemId ) ;
else
fprintf ( SAXdebug , " , ) \n " ) ;
/*********
if ( systemId ! = NULL ) {
return ( xmlNewInputFromFile ( ctxt , ( char * ) systemId ) ) ;
}
* * * * * * * * */
return ( NULL ) ;
}
/**
* getEntityDebug :
* @ ctxt : An XML parser context
* @ name : The entity name
*
* Get an entity by name
*
* Returns the xmlParserInputPtr if inlined or NULL for DOM behaviour .
*/
static xmlEntityPtr
2023-10-06 11:44:38 +03:00
getEntityDebug ( void * ctx , const xmlChar * name )
2005-07-07 00:41:33 +04:00
{
2023-10-06 11:44:38 +03:00
debugContext * ctxt = ctx ;
2005-07-07 00:41:33 +04:00
callbacks + + ;
if ( quiet )
return ( NULL ) ;
fprintf ( SAXdebug , " SAX.getEntity(%s) \n " , name ) ;
2023-10-06 11:44:38 +03:00
return ( xmlHashLookup ( ctxt - > generalEntities , name ) ) ;
2005-07-07 00:41:33 +04:00
}
/**
* getParameterEntityDebug :
* @ ctxt : An XML parser context
* @ name : The entity name
*
* Get a parameter entity by name
*
* Returns the xmlParserInputPtr
*/
static xmlEntityPtr
2023-10-06 11:44:38 +03:00
getParameterEntityDebug ( void * ctx , const xmlChar * name )
2005-07-07 00:41:33 +04:00
{
2023-10-06 11:44:38 +03:00
debugContext * ctxt = ctx ;
2005-07-07 00:41:33 +04:00
callbacks + + ;
if ( quiet )
return ( NULL ) ;
fprintf ( SAXdebug , " SAX.getParameterEntity(%s) \n " , name ) ;
2023-10-06 11:44:38 +03:00
return ( xmlHashLookup ( ctxt - > parameterEntities , name ) ) ;
2005-07-07 00:41:33 +04:00
}
/**
* entityDeclDebug :
* @ ctxt : An XML parser context
2008-08-25 18:53:31 +04:00
* @ name : the entity name
* @ type : the entity type
2005-07-07 00:41:33 +04:00
* @ publicId : The public ID of the entity
* @ systemId : The system ID of the entity
* @ content : the entity value ( without processing ) .
*
* An entity definition has been parsed
*/
static void
2023-10-06 11:44:38 +03:00
entityDeclDebug ( void * ctx , const xmlChar * name , int type ,
2005-07-07 00:41:33 +04:00
const xmlChar * publicId , const xmlChar * systemId , xmlChar * content )
{
2023-10-06 11:44:38 +03:00
debugContext * ctxt = ctx ;
xmlEntityPtr ent ;
const xmlChar * nullstr = BAD_CAST " (null) " ;
2023-12-23 02:00:15 +03:00
ent = xmlNewEntity ( NULL , name , type , publicId , systemId , content ) ;
if ( systemId ! = NULL )
ent - > URI = xmlBuildURI ( systemId , ( const xmlChar * ) ctxt - > filename ) ;
if ( ( type = = XML_INTERNAL_PARAMETER_ENTITY ) | |
( type = = XML_EXTERNAL_PARAMETER_ENTITY ) )
xmlHashAddEntry ( ctxt - > parameterEntities , name , ent ) ;
else
xmlHashAddEntry ( ctxt - > generalEntities , name , ent ) ;
2005-07-07 00:41:33 +04:00
/* not all libraries handle printing null pointers nicely */
if ( publicId = = NULL )
publicId = nullstr ;
if ( systemId = = NULL )
systemId = nullstr ;
if ( content = = NULL )
content = ( xmlChar * ) nullstr ;
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.entityDecl(%s, %d, %s, %s, %s) \n " ,
name , type , publicId , systemId , content ) ;
}
/**
* attributeDeclDebug :
* @ ctxt : An XML parser context
2008-08-25 18:53:31 +04:00
* @ name : the attribute name
* @ type : the attribute type
2005-07-07 00:41:33 +04:00
*
* An attribute definition has been parsed
*/
static void
attributeDeclDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * elem ,
const xmlChar * name , int type , int def ,
const xmlChar * defaultValue , xmlEnumerationPtr tree )
{
callbacks + + ;
if ( quiet )
return ;
if ( defaultValue = = NULL )
fprintf ( SAXdebug , " SAX.attributeDecl(%s, %s, %d, %d, NULL, ...) \n " ,
elem , name , type , def ) ;
else
fprintf ( SAXdebug , " SAX.attributeDecl(%s, %s, %d, %d, %s, ...) \n " ,
elem , name , type , def , defaultValue ) ;
xmlFreeEnumeration ( tree ) ;
}
/**
* elementDeclDebug :
* @ ctxt : An XML parser context
2008-08-25 18:53:31 +04:00
* @ name : the element name
* @ type : the element type
2005-07-07 00:41:33 +04:00
* @ content : the element value ( without processing ) .
*
* An element definition has been parsed
*/
static void
elementDeclDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * name , int type ,
xmlElementContentPtr content ATTRIBUTE_UNUSED )
{
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.elementDecl(%s, %d, ...) \n " ,
name , type ) ;
}
/**
* notationDeclDebug :
* @ ctxt : An XML parser context
* @ name : The name of the notation
* @ publicId : The public ID of the entity
* @ systemId : The system ID of the entity
*
* What to do when a notation declaration has been parsed .
*/
static void
notationDeclDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * name ,
const xmlChar * publicId , const xmlChar * systemId )
{
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.notationDecl(%s, %s, %s) \n " ,
( char * ) name , ( char * ) publicId , ( char * ) systemId ) ;
}
/**
* unparsedEntityDeclDebug :
* @ ctxt : An XML parser context
* @ name : The name of the entity
* @ publicId : The public ID of the entity
* @ systemId : The system ID of the entity
* @ notationName : the name of the notation
*
* What to do when an unparsed entity declaration is parsed
*/
static void
unparsedEntityDeclDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * name ,
const xmlChar * publicId , const xmlChar * systemId ,
const xmlChar * notationName )
{
const xmlChar * nullstr = BAD_CAST " (null) " ;
if ( publicId = = NULL )
publicId = nullstr ;
if ( systemId = = NULL )
systemId = nullstr ;
if ( notationName = = NULL )
notationName = nullstr ;
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.unparsedEntityDecl(%s, %s, %s, %s) \n " ,
( char * ) name , ( char * ) publicId , ( char * ) systemId ,
( char * ) notationName ) ;
}
/**
* setDocumentLocatorDebug :
* @ ctxt : An XML parser context
* @ loc : A SAX Locator
*
* Receive the document locator at startup , actually xmlDefaultSAXLocator
* Everything is available on the context , so this is useless in our case .
*/
static void
setDocumentLocatorDebug ( void * ctx ATTRIBUTE_UNUSED , xmlSAXLocatorPtr loc ATTRIBUTE_UNUSED )
{
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.setDocumentLocator() \n " ) ;
}
/**
* startDocumentDebug :
* @ ctxt : An XML parser context
*
* called when the document start being processed .
*/
static void
startDocumentDebug ( void * ctx ATTRIBUTE_UNUSED )
{
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.startDocument() \n " ) ;
}
/**
* endDocumentDebug :
* @ ctxt : An XML parser context
*
* called when the document end has been detected .
*/
static void
endDocumentDebug ( void * ctx ATTRIBUTE_UNUSED )
{
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.endDocument() \n " ) ;
}
/**
* startElementDebug :
* @ ctxt : An XML parser context
* @ name : The element name
*
* called when an opening tag has been processed .
*/
static void
startElementDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * name , const xmlChar * * atts )
{
int i ;
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.startElement(%s " , ( char * ) name ) ;
if ( atts ! = NULL ) {
for ( i = 0 ; ( atts [ i ] ! = NULL ) ; i + + ) {
fprintf ( SAXdebug , " , %s=' " , atts [ i + + ] ) ;
if ( atts [ i ] ! = NULL )
fprintf ( SAXdebug , " %s' " , atts [ i ] ) ;
}
}
fprintf ( SAXdebug , " ) \n " ) ;
}
/**
* endElementDebug :
* @ ctxt : An XML parser context
* @ name : The element name
*
* called when the end of an element has been detected .
*/
static void
endElementDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * name )
{
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.endElement(%s) \n " , ( char * ) name ) ;
}
/**
* charactersDebug :
* @ ctxt : An XML parser context
* @ ch : a xmlChar string
* @ len : the number of xmlChar
*
* receiving some chars from the parser .
* Question : how much at a time ? ? ?
*/
static void
charactersDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * ch , int len )
{
char output [ 40 ] ;
int i ;
callbacks + + ;
if ( quiet )
return ;
for ( i = 0 ; ( i < len ) & & ( i < 30 ) ; i + + )
2022-01-25 04:34:40 +03:00
output [ i ] = ( char ) ch [ i ] ;
2005-07-07 00:41:33 +04:00
output [ i ] = 0 ;
fprintf ( SAXdebug , " SAX.characters(%s, %d) \n " , output , len ) ;
}
/**
* referenceDebug :
* @ ctxt : An XML parser context
* @ name : The entity name
*
2008-08-25 18:53:31 +04:00
* called when an entity reference is detected .
2005-07-07 00:41:33 +04:00
*/
static void
referenceDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * name )
{
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.reference(%s) \n " , name ) ;
}
/**
* ignorableWhitespaceDebug :
* @ ctxt : An XML parser context
* @ ch : a xmlChar string
* @ start : the first char in the string
* @ len : the number of xmlChar
*
* receiving some ignorable whitespaces from the parser .
* Question : how much at a time ? ? ?
*/
static void
ignorableWhitespaceDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * ch , int len )
{
char output [ 40 ] ;
int i ;
callbacks + + ;
if ( quiet )
return ;
for ( i = 0 ; ( i < len ) & & ( i < 30 ) ; i + + )
2022-01-25 04:34:40 +03:00
output [ i ] = ( char ) ch [ i ] ;
2005-07-07 00:41:33 +04:00
output [ i ] = 0 ;
fprintf ( SAXdebug , " SAX.ignorableWhitespace(%s, %d) \n " , output , len ) ;
}
/**
* processingInstructionDebug :
* @ ctxt : An XML parser context
* @ target : the target name
* @ data : the PI data ' s
* @ len : the number of xmlChar
*
* A processing instruction has been parsed .
*/
static void
processingInstructionDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * target ,
const xmlChar * data )
{
callbacks + + ;
if ( quiet )
return ;
if ( data ! = NULL )
fprintf ( SAXdebug , " SAX.processingInstruction(%s, %s) \n " ,
( char * ) target , ( char * ) data ) ;
else
fprintf ( SAXdebug , " SAX.processingInstruction(%s, NULL) \n " ,
( char * ) target ) ;
}
/**
* cdataBlockDebug :
* @ ctx : the user data ( XML parser context )
* @ value : The pcdata content
* @ len : the block length
*
* called when a pcdata block has been parsed
*/
static void
cdataBlockDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * value , int len )
{
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.pcdata(%.20s, %d) \n " ,
( char * ) value , len ) ;
}
/**
* commentDebug :
* @ ctxt : An XML parser context
* @ value : the comment content
*
* A comment has been parsed .
*/
static void
commentDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * value )
{
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.comment(%s) \n " , value ) ;
}
/**
* warningDebug :
* @ ctxt : An XML parser context
* @ msg : the message to display / transmit
* @ . . . : extra parameters for the message display
*
* Display and format a warning messages , gives file , line , position and
* extra parameters .
*/
2022-12-08 04:43:17 +03:00
static void
2005-07-07 00:41:33 +04:00
warningDebug ( void * ctx ATTRIBUTE_UNUSED , const char * msg , . . . )
{
va_list args ;
callbacks + + ;
if ( quiet )
return ;
va_start ( args , msg ) ;
fprintf ( SAXdebug , " SAX.warning: " ) ;
vfprintf ( SAXdebug , msg , args ) ;
va_end ( args ) ;
}
/**
* errorDebug :
* @ ctxt : An XML parser context
* @ msg : the message to display / transmit
* @ . . . : extra parameters for the message display
*
* Display and format a error messages , gives file , line , position and
* extra parameters .
*/
2022-12-08 04:43:17 +03:00
static void
2005-07-07 00:41:33 +04:00
errorDebug ( void * ctx ATTRIBUTE_UNUSED , const char * msg , . . . )
{
va_list args ;
callbacks + + ;
if ( quiet )
return ;
va_start ( args , msg ) ;
fprintf ( SAXdebug , " SAX.error: " ) ;
vfprintf ( SAXdebug , msg , args ) ;
va_end ( args ) ;
}
/**
* fatalErrorDebug :
* @ ctxt : An XML parser context
* @ msg : the message to display / transmit
* @ . . . : extra parameters for the message display
*
* Display and format a fatalError messages , gives file , line , position and
* extra parameters .
*/
2022-12-08 04:43:17 +03:00
static void
2005-07-07 00:41:33 +04:00
fatalErrorDebug ( void * ctx ATTRIBUTE_UNUSED , const char * msg , . . . )
{
va_list args ;
callbacks + + ;
if ( quiet )
return ;
va_start ( args , msg ) ;
fprintf ( SAXdebug , " SAX.fatalError: " ) ;
vfprintf ( SAXdebug , msg , args ) ;
va_end ( args ) ;
}
2005-07-29 03:49:35 +04:00
static xmlSAXHandler debugSAXHandlerStruct = {
2005-07-07 00:41:33 +04:00
internalSubsetDebug ,
isStandaloneDebug ,
hasInternalSubsetDebug ,
hasExternalSubsetDebug ,
resolveEntityDebug ,
getEntityDebug ,
entityDeclDebug ,
notationDeclDebug ,
attributeDeclDebug ,
elementDeclDebug ,
unparsedEntityDeclDebug ,
setDocumentLocatorDebug ,
startDocumentDebug ,
endDocumentDebug ,
startElementDebug ,
endElementDebug ,
referenceDebug ,
charactersDebug ,
ignorableWhitespaceDebug ,
processingInstructionDebug ,
commentDebug ,
warningDebug ,
errorDebug ,
fatalErrorDebug ,
getParameterEntityDebug ,
cdataBlockDebug ,
externalSubsetDebug ,
1 ,
NULL ,
NULL ,
NULL ,
NULL
} ;
2005-07-29 03:49:35 +04:00
static xmlSAXHandlerPtr debugSAXHandler = & debugSAXHandlerStruct ;
2005-07-07 00:41:33 +04:00
/*
* SAX2 specific callbacks
*/
/**
* startElementNsDebug :
* @ ctxt : An XML parser context
* @ name : The element name
*
* called when an opening tag has been processed .
*/
static void
startElementNsDebug ( void * ctx ATTRIBUTE_UNUSED ,
const xmlChar * localname ,
const xmlChar * prefix ,
const xmlChar * URI ,
int nb_namespaces ,
const xmlChar * * namespaces ,
int nb_attributes ,
int nb_defaulted ,
const xmlChar * * attributes )
{
int i ;
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.startElementNs(%s " , ( char * ) localname ) ;
if ( prefix = = NULL )
fprintf ( SAXdebug , " , NULL " ) ;
else
fprintf ( SAXdebug , " , %s " , ( char * ) prefix ) ;
if ( URI = = NULL )
fprintf ( SAXdebug , " , NULL " ) ;
else
fprintf ( SAXdebug , " , '%s' " , ( char * ) URI ) ;
fprintf ( SAXdebug , " , %d " , nb_namespaces ) ;
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
if ( namespaces ! = NULL ) {
for ( i = 0 ; i < nb_namespaces * 2 ; i + + ) {
fprintf ( SAXdebug , " , xmlns " ) ;
if ( namespaces [ i ] ! = NULL )
fprintf ( SAXdebug , " :%s " , namespaces [ i ] ) ;
i + + ;
fprintf ( SAXdebug , " ='%s' " , namespaces [ i ] ) ;
}
}
fprintf ( SAXdebug , " , %d, %d " , nb_attributes , nb_defaulted ) ;
if ( attributes ! = NULL ) {
for ( i = 0 ; i < nb_attributes * 5 ; i + = 5 ) {
if ( attributes [ i + 1 ] ! = NULL )
fprintf ( SAXdebug , " , %s:%s=' " , attributes [ i + 1 ] , attributes [ i ] ) ;
else
fprintf ( SAXdebug , " , %s=' " , attributes [ i ] ) ;
fprintf ( SAXdebug , " %.4s...', %d " , attributes [ i + 3 ] ,
( int ) ( attributes [ i + 4 ] - attributes [ i + 3 ] ) ) ;
}
}
fprintf ( SAXdebug , " ) \n " ) ;
}
/**
* endElementDebug :
* @ ctxt : An XML parser context
* @ name : The element name
*
* called when the end of an element has been detected .
*/
static void
endElementNsDebug ( void * ctx ATTRIBUTE_UNUSED ,
const xmlChar * localname ,
const xmlChar * prefix ,
const xmlChar * URI )
{
callbacks + + ;
if ( quiet )
return ;
fprintf ( SAXdebug , " SAX.endElementNs(%s " , ( char * ) localname ) ;
if ( prefix = = NULL )
fprintf ( SAXdebug , " , NULL " ) ;
else
fprintf ( SAXdebug , " , %s " , ( char * ) prefix ) ;
if ( URI = = NULL )
fprintf ( SAXdebug , " , NULL) \n " ) ;
else
fprintf ( SAXdebug , " , '%s') \n " , ( char * ) URI ) ;
}
2005-07-29 03:49:35 +04:00
static xmlSAXHandler debugSAX2HandlerStruct = {
2005-07-07 00:41:33 +04:00
internalSubsetDebug ,
isStandaloneDebug ,
hasInternalSubsetDebug ,
hasExternalSubsetDebug ,
resolveEntityDebug ,
getEntityDebug ,
entityDeclDebug ,
notationDeclDebug ,
attributeDeclDebug ,
elementDeclDebug ,
unparsedEntityDeclDebug ,
setDocumentLocatorDebug ,
startDocumentDebug ,
endDocumentDebug ,
NULL ,
NULL ,
referenceDebug ,
charactersDebug ,
ignorableWhitespaceDebug ,
processingInstructionDebug ,
commentDebug ,
warningDebug ,
errorDebug ,
fatalErrorDebug ,
getParameterEntityDebug ,
cdataBlockDebug ,
externalSubsetDebug ,
XML_SAX2_MAGIC ,
NULL ,
startElementNsDebug ,
endElementNsDebug ,
NULL
} ;
2005-07-29 03:49:35 +04:00
static xmlSAXHandlerPtr debugSAX2Handler = & debugSAX2HandlerStruct ;
2005-07-07 00:41:33 +04:00
# ifdef LIBXML_HTML_ENABLED
/**
* htmlstartElementDebug :
* @ ctxt : An XML parser context
* @ name : The element name
*
* called when an opening tag has been processed .
*/
static void
htmlstartElementDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * name , const xmlChar * * atts )
{
int i ;
fprintf ( SAXdebug , " SAX.startElement(%s " , ( char * ) name ) ;
if ( atts ! = NULL ) {
for ( i = 0 ; ( atts [ i ] ! = NULL ) ; i + + ) {
fprintf ( SAXdebug , " , %s " , atts [ i + + ] ) ;
if ( atts [ i ] ! = NULL ) {
unsigned char output [ 40 ] ;
const unsigned char * att = atts [ i ] ;
int outlen , attlen ;
fprintf ( SAXdebug , " =' " ) ;
while ( ( attlen = strlen ( ( char * ) att ) ) > 0 ) {
outlen = sizeof output - 1 ;
htmlEncodeEntities ( output , & outlen , att , & attlen , ' \' ' ) ;
output [ outlen ] = 0 ;
fprintf ( SAXdebug , " %s " , ( char * ) output ) ;
att + = attlen ;
}
fprintf ( SAXdebug , " ' " ) ;
}
}
}
fprintf ( SAXdebug , " ) \n " ) ;
}
/**
* htmlcharactersDebug :
* @ ctxt : An XML parser context
* @ ch : a xmlChar string
* @ len : the number of xmlChar
*
* receiving some chars from the parser .
* Question : how much at a time ? ? ?
*/
static void
htmlcharactersDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * ch , int len )
{
unsigned char output [ 40 ] ;
int inlen = len , outlen = 30 ;
htmlEncodeEntities ( output , & outlen , ch , & inlen , 0 ) ;
output [ outlen ] = 0 ;
fprintf ( SAXdebug , " SAX.characters(%s, %d) \n " , output , len ) ;
}
/**
* htmlcdataDebug :
* @ ctxt : An XML parser context
* @ ch : a xmlChar string
* @ len : the number of xmlChar
*
* receiving some cdata chars from the parser .
* Question : how much at a time ? ? ?
*/
static void
htmlcdataDebug ( void * ctx ATTRIBUTE_UNUSED , const xmlChar * ch , int len )
{
unsigned char output [ 40 ] ;
int inlen = len , outlen = 30 ;
htmlEncodeEntities ( output , & outlen , ch , & inlen , 0 ) ;
output [ outlen ] = 0 ;
fprintf ( SAXdebug , " SAX.cdata(%s, %d) \n " , output , len ) ;
}
2005-07-29 03:49:35 +04:00
static xmlSAXHandler debugHTMLSAXHandlerStruct = {
2005-07-07 00:41:33 +04:00
internalSubsetDebug ,
isStandaloneDebug ,
hasInternalSubsetDebug ,
hasExternalSubsetDebug ,
resolveEntityDebug ,
getEntityDebug ,
entityDeclDebug ,
notationDeclDebug ,
attributeDeclDebug ,
elementDeclDebug ,
unparsedEntityDeclDebug ,
setDocumentLocatorDebug ,
startDocumentDebug ,
endDocumentDebug ,
htmlstartElementDebug ,
endElementDebug ,
referenceDebug ,
htmlcharactersDebug ,
ignorableWhitespaceDebug ,
processingInstructionDebug ,
commentDebug ,
warningDebug ,
errorDebug ,
fatalErrorDebug ,
getParameterEntityDebug ,
htmlcdataDebug ,
externalSubsetDebug ,
1 ,
NULL ,
NULL ,
NULL ,
NULL
} ;
2005-07-29 03:49:35 +04:00
static xmlSAXHandlerPtr debugHTMLSAXHandler = & debugHTMLSAXHandlerStruct ;
2005-07-07 00:41:33 +04:00
# endif /* LIBXML_HTML_ENABLED */
2023-10-06 11:44:38 +03:00
static void
hashFreeEntity ( void * payload , const xmlChar * name ATTRIBUTE_UNUSED ) {
xmlEntityPtr ent = payload ;
xmlFreeEntity ( ent ) ;
}
2005-07-07 00:41:33 +04:00
/**
* saxParseTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file using the SAX API and check for errors .
*
* Returns 0 in case of success , an error code otherwise
*/
static int
saxParseTest ( const char * filename , const char * result ,
const char * err ATTRIBUTE_UNUSED ,
int options ) {
int ret ;
char * temp ;
nb_tests + + ;
2020-06-04 12:58:04 +03:00
temp = resultFilename ( filename , temp_directory , " .res " ) ;
2005-07-07 00:41:33 +04:00
if ( temp = = NULL ) {
fprintf ( stderr , " out of memory \n " ) ;
fatalError ( ) ;
}
SAXdebug = fopen ( temp , " wb " ) ;
if ( SAXdebug = = NULL ) {
fprintf ( stderr , " Failed to write to %s \n " , temp ) ;
free ( temp ) ;
return ( - 1 ) ;
}
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML ) {
2022-08-25 21:18:16 +03:00
htmlParserCtxtPtr ctxt ;
ctxt = htmlNewSAXParserCtxt ( emptySAXHandler , NULL ) ;
htmlCtxtReadFile ( ctxt , filename , NULL , options ) ;
htmlFreeParserCtxt ( ctxt ) ;
2005-07-07 00:41:33 +04:00
ret = 0 ;
} else
# endif
2017-06-16 22:38:57 +03:00
{
xmlParserCtxtPtr ctxt = xmlCreateFileParserCtxt ( filename ) ;
memcpy ( ctxt - > sax , emptySAXHandler , sizeof ( xmlSAXHandler ) ) ;
xmlCtxtUseOptions ( ctxt , options ) ;
xmlParseDocument ( ctxt ) ;
ret = ctxt - > wellFormed ? 0 : ctxt - > errNo ;
xmlFreeDoc ( ctxt - > myDoc ) ;
xmlFreeParserCtxt ( ctxt ) ;
}
2024-04-22 16:42:39 +03:00
if ( ret = = XML_ERR_UNDECLARED_ENTITY ) {
fprintf ( SAXdebug , " xmlParseDocument returned error %d \n " , ret ) ;
2005-07-07 00:41:33 +04:00
ret = 0 ;
}
if ( ret ! = 0 ) {
fprintf ( stderr , " Failed to parse %s \n " , filename ) ;
2014-06-21 00:15:16 +04:00
ret = 1 ;
goto done ;
2005-07-07 00:41:33 +04:00
}
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML ) {
2022-08-25 21:18:16 +03:00
htmlParserCtxtPtr ctxt ;
ctxt = htmlNewSAXParserCtxt ( debugHTMLSAXHandler , NULL ) ;
htmlCtxtReadFile ( ctxt , filename , NULL , options ) ;
htmlFreeParserCtxt ( ctxt ) ;
2005-07-07 00:41:33 +04:00
ret = 0 ;
} else
# endif
2017-06-16 22:38:57 +03:00
{
2023-10-06 11:44:38 +03:00
debugContext userData ;
2017-06-16 22:38:57 +03:00
xmlParserCtxtPtr ctxt = xmlCreateFileParserCtxt ( filename ) ;
2023-10-06 11:44:38 +03:00
2017-06-16 22:38:57 +03:00
if ( options & XML_PARSE_SAX1 ) {
memcpy ( ctxt - > sax , debugSAXHandler , sizeof ( xmlSAXHandler ) ) ;
options - = XML_PARSE_SAX1 ;
} else {
memcpy ( ctxt - > sax , debugSAX2Handler , sizeof ( xmlSAXHandler ) ) ;
}
2023-10-06 11:44:38 +03:00
userData . filename = filename ;
userData . generalEntities = xmlHashCreate ( 0 ) ;
userData . parameterEntities = xmlHashCreate ( 0 ) ;
ctxt - > userData = & userData ;
2017-06-16 22:38:57 +03:00
xmlCtxtUseOptions ( ctxt , options ) ;
xmlParseDocument ( ctxt ) ;
ret = ctxt - > wellFormed ? 0 : ctxt - > errNo ;
2023-10-06 11:44:38 +03:00
xmlHashFree ( userData . generalEntities , hashFreeEntity ) ;
xmlHashFree ( userData . parameterEntities , hashFreeEntity ) ;
2017-06-16 22:38:57 +03:00
xmlFreeDoc ( ctxt - > myDoc ) ;
xmlFreeParserCtxt ( ctxt ) ;
2005-07-07 00:41:33 +04:00
}
fclose ( SAXdebug ) ;
if ( compareFiles ( temp , result ) ) {
fprintf ( stderr , " Got a difference for %s \n " , filename ) ;
ret = 1 ;
2009-09-05 16:52:55 +04:00
}
2014-06-21 00:15:16 +04:00
done :
2009-09-05 16:52:55 +04:00
if ( temp ! = NULL ) {
unlink ( temp ) ;
free ( temp ) ;
}
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
return ( ret ) ;
}
/************************************************************************
* *
* Parse to tree based tests *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
* oldParseTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages : unused
*
* Parse a file using the old xmlParseFile API , then serialize back
* reparse the result and serialize again , then check for deviation
* in serialization .
*
* Returns 0 in case of success , an error code otherwise
*/
static int
oldParseTest ( const char * filename , const char * result ,
const char * err ATTRIBUTE_UNUSED ,
int options ATTRIBUTE_UNUSED ) {
xmlDocPtr doc ;
char * temp ;
int res = 0 ;
nb_tests + + ;
/*
* base of the test , parse with the old API
*/
# ifdef LIBXML_SAX1_ENABLED
2024-05-02 17:23:04 +03:00
xmlGetWarningsDefaultValue = 0 ;
2005-07-07 00:41:33 +04:00
doc = xmlParseFile ( filename ) ;
2024-05-02 17:23:04 +03:00
xmlGetWarningsDefaultValue = 1 ;
2005-07-07 00:41:33 +04:00
# else
2024-05-02 17:23:04 +03:00
doc = xmlReadFile ( filename , NULL , XML_PARSE_NOWARNING ) ;
2005-07-07 00:41:33 +04:00
# endif
2024-01-04 15:59:23 +03:00
if ( doc = = NULL )
return ( 1 ) ;
2020-06-04 12:58:04 +03:00
temp = resultFilename ( filename , temp_directory , " .res " ) ;
2005-07-07 00:41:33 +04:00
if ( temp = = NULL ) {
fprintf ( stderr , " out of memory \n " ) ;
fatalError ( ) ;
}
xmlSaveFile ( temp , doc ) ;
if ( compareFiles ( temp , result ) ) {
res = 1 ;
}
xmlFreeDoc ( doc ) ;
/*
* Parse the saved result to make sure the round trip is okay
*/
# ifdef LIBXML_SAX1_ENABLED
2024-05-02 17:23:04 +03:00
xmlGetWarningsDefaultValue = 0 ;
2005-07-07 00:41:33 +04:00
doc = xmlParseFile ( temp ) ;
2024-05-02 17:23:04 +03:00
xmlGetWarningsDefaultValue = 1 ;
2005-07-07 00:41:33 +04:00
# else
2024-05-02 17:23:04 +03:00
doc = xmlReadFile ( temp , NULL , XML_PARSE_NOWARNING ) ;
2005-07-07 00:41:33 +04:00
# endif
2024-01-04 15:59:23 +03:00
if ( doc = = NULL )
return ( 1 ) ;
2005-07-07 00:41:33 +04:00
xmlSaveFile ( temp , doc ) ;
if ( compareFiles ( temp , result ) ) {
res = 1 ;
}
xmlFreeDoc ( doc ) ;
2009-09-05 16:52:55 +04:00
if ( temp ! = NULL ) {
unlink ( temp ) ;
free ( temp ) ;
}
2023-12-18 23:41:30 +03:00
2005-07-07 00:41:33 +04:00
return ( res ) ;
}
# ifdef LIBXML_PUSH_ENABLED
/**
* pushParseTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages : unused
*
* Parse a file using the Push API , then serialize back
* to check for content .
*
* Returns 0 in case of success , an error code otherwise
*/
static int
pushParseTest ( const char * filename , const char * result ,
const char * err ATTRIBUTE_UNUSED ,
int options ) {
xmlParserCtxtPtr ctxt ;
xmlDocPtr doc ;
const char * base ;
int size , res ;
int cur = 0 ;
2017-06-12 19:26:11 +03:00
int chunkSize = 4 ;
2005-07-07 00:41:33 +04:00
nb_tests + + ;
/*
* load the document in memory and work from there .
*/
if ( loadMem ( filename , & base , & size ) ! = 0 ) {
fprintf ( stderr , " Failed to load %s \n " , filename ) ;
return ( - 1 ) ;
}
2008-08-25 18:53:31 +04:00
2017-06-12 19:26:11 +03:00
if ( chunkSize > size )
chunkSize = size ;
2005-07-07 00:41:33 +04:00
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML )
2017-06-12 19:26:11 +03:00
ctxt = htmlCreatePushParserCtxt ( NULL , NULL , base + cur , chunkSize , filename ,
2005-07-07 00:41:33 +04:00
XML_CHAR_ENCODING_NONE ) ;
else
# endif
2017-06-12 19:26:11 +03:00
ctxt = xmlCreatePushParserCtxt ( NULL , NULL , base + cur , chunkSize , filename ) ;
2023-12-18 23:41:30 +03:00
xmlCtxtSetErrorHandler ( ctxt , testStructuredErrorHandler , NULL ) ;
2005-07-07 00:41:33 +04:00
xmlCtxtUseOptions ( ctxt , options ) ;
2017-06-12 19:26:11 +03:00
cur + = chunkSize ;
chunkSize = 1024 ;
2016-03-01 22:34:04 +03:00
do {
2017-06-12 19:26:11 +03:00
if ( cur + chunkSize > = size ) {
2005-07-07 00:41:33 +04:00
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML )
htmlParseChunk ( ctxt , base + cur , size - cur , 1 ) ;
else
# endif
xmlParseChunk ( ctxt , base + cur , size - cur , 1 ) ;
break ;
} else {
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML )
2017-06-12 19:26:11 +03:00
htmlParseChunk ( ctxt , base + cur , chunkSize , 0 ) ;
2005-07-07 00:41:33 +04:00
else
# endif
2017-06-12 19:26:11 +03:00
xmlParseChunk ( ctxt , base + cur , chunkSize , 0 ) ;
cur + = chunkSize ;
2005-07-07 00:41:33 +04:00
}
2016-03-01 22:34:04 +03:00
} while ( cur < size ) ;
2005-07-07 00:41:33 +04:00
doc = ctxt - > myDoc ;
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML )
res = 1 ;
else
# endif
res = ctxt - > wellFormed ;
xmlFreeParserCtxt ( ctxt ) ;
free ( ( char * ) base ) ;
if ( ! res ) {
xmlFreeDoc ( doc ) ;
fprintf ( stderr , " Failed to parse %s \n " , filename ) ;
return ( - 1 ) ;
}
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML )
htmlDocDumpMemory ( doc , ( xmlChar * * ) & base , & size ) ;
else
# endif
xmlDocDumpMemory ( doc , ( xmlChar * * ) & base , & size ) ;
xmlFreeDoc ( doc ) ;
res = compareFileMem ( result , base , size ) ;
if ( ( base = = NULL ) | | ( res ! = 0 ) ) {
if ( base ! = NULL )
xmlFree ( ( char * ) base ) ;
2016-05-22 06:14:45 +03:00
fprintf ( stderr , " Result for %s failed in %s \n " , filename , result ) ;
2005-07-07 00:41:33 +04:00
return ( - 1 ) ;
}
xmlFree ( ( char * ) base ) ;
if ( err ! = NULL ) {
res = compareFileMem ( err , testErrors , testErrorsSize ) ;
if ( res ! = 0 ) {
fprintf ( stderr , " Error for %s failed \n " , filename ) ;
return ( - 1 ) ;
}
}
return ( 0 ) ;
}
2022-11-20 17:36:41 +03:00
static int pushBoundaryCount ;
static int pushBoundaryRefCount ;
static int pushBoundaryCharsCount ;
static int pushBoundaryCDataCount ;
static void
internalSubsetBnd ( void * ctx , const xmlChar * name , const xmlChar * externalID ,
const xmlChar * systemID ) {
pushBoundaryCount + + ;
xmlSAX2InternalSubset ( ctx , name , externalID , systemID ) ;
}
static void
referenceBnd ( void * ctx , const xmlChar * name ) {
pushBoundaryRefCount + + ;
xmlSAX2Reference ( ctx , name ) ;
}
static void
charactersBnd ( void * ctx , const xmlChar * ch , int len ) {
pushBoundaryCount + + ;
pushBoundaryCharsCount + + ;
xmlSAX2Characters ( ctx , ch , len ) ;
}
static void
cdataBlockBnd ( void * ctx , const xmlChar * ch , int len ) {
pushBoundaryCount + + ;
pushBoundaryCDataCount + + ;
xmlSAX2CDataBlock ( ctx , ch , len ) ;
}
static void
processingInstructionBnd ( void * ctx , const xmlChar * target ,
const xmlChar * data ) {
pushBoundaryCount + + ;
xmlSAX2ProcessingInstruction ( ctx , target , data ) ;
}
static void
commentBnd ( void * ctx , const xmlChar * value ) {
xmlParserCtxtPtr ctxt = ctx ;
if ( ctxt - > inSubset = = 0 )
pushBoundaryCount + + ;
xmlSAX2Comment ( ctx , value ) ;
}
static void
startElementBnd ( void * ctx , const xmlChar * xname , const xmlChar * * atts ) {
const char * name = ( const char * ) xname ;
/* Some elements might be created automatically. */
if ( ( strcmp ( name , " html " ) ! = 0 ) & &
( strcmp ( name , " body " ) ! = 0 ) & &
( strcmp ( name , " head " ) ! = 0 ) & &
( strcmp ( name , " p " ) ! = 0 ) ) {
pushBoundaryCount + + ;
}
xmlSAX2StartElement ( ctx , xname , atts ) ;
}
static void
endElementBnd ( void * ctx , const xmlChar * name ) {
/*pushBoundaryCount++;*/
xmlSAX2EndElement ( ctx , name ) ;
}
static void
startElementNsBnd ( void * ctx , const xmlChar * localname , const xmlChar * prefix ,
const xmlChar * URI , int nb_namespaces ,
const xmlChar * * namespaces , int nb_attributes ,
int nb_defaulted , const xmlChar * * attributes ) {
pushBoundaryCount + + ;
xmlSAX2StartElementNs ( ctx , localname , prefix , URI , nb_namespaces ,
namespaces , nb_attributes , nb_defaulted , attributes ) ;
}
static void
endElementNsBnd ( void * ctx , const xmlChar * localname , const xmlChar * prefix ,
const xmlChar * URI ) {
/*pushBoundaryCount++;*/
xmlSAX2EndElementNs ( ctx , localname , prefix , URI ) ;
}
/**
* pushBoundaryTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages : unused
*
* Test whether the push parser detects boundaries between syntactical
* elements correctly .
*
* Returns 0 in case of success , an error code otherwise
*/
static int
pushBoundaryTest ( const char * filename , const char * result ,
const char * err ATTRIBUTE_UNUSED ,
int options ) {
xmlParserCtxtPtr ctxt ;
xmlDocPtr doc ;
xmlSAXHandler bndSAX ;
const char * base ;
int size , res , numCallbacks ;
int cur = 0 ;
unsigned long avail , oldConsumed , consumed ;
2023-11-30 18:15:46 +03:00
/*
* HTML encoding detection doesn ' t work when data is fed bytewise .
*/
if ( strcmp ( filename , " ./test/HTML/xml-declaration-1.html " ) = = 0 )
return ( 0 ) ;
2022-11-20 17:36:41 +03:00
/*
* If the parser made progress , check that exactly one construct was
* processed and that the input buffer is ( almost ) empty .
* Since we use a chunk size of 1 , this tests whether content is
* processed as early as possible .
*/
nb_tests + + ;
memset ( & bndSAX , 0 , sizeof ( bndSAX ) ) ;
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML ) {
xmlSAX2InitHtmlDefaultSAXHandler ( & bndSAX ) ;
bndSAX . startElement = startElementBnd ;
bndSAX . endElement = endElementBnd ;
} else
# endif
{
xmlSAXVersion ( & bndSAX , 2 ) ;
bndSAX . startElementNs = startElementNsBnd ;
bndSAX . endElementNs = endElementNsBnd ;
}
bndSAX . internalSubset = internalSubsetBnd ;
bndSAX . reference = referenceBnd ;
bndSAX . characters = charactersBnd ;
bndSAX . cdataBlock = cdataBlockBnd ;
bndSAX . processingInstruction = processingInstructionBnd ;
bndSAX . comment = commentBnd ;
/*
* load the document in memory and work from there .
*/
if ( loadMem ( filename , & base , & size ) ! = 0 ) {
fprintf ( stderr , " Failed to load %s \n " , filename ) ;
return ( - 1 ) ;
}
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML )
ctxt = htmlCreatePushParserCtxt ( & bndSAX , NULL , base , 1 , filename ,
XML_CHAR_ENCODING_NONE ) ;
else
# endif
ctxt = xmlCreatePushParserCtxt ( & bndSAX , NULL , base , 1 , filename ) ;
2023-12-18 23:41:30 +03:00
xmlCtxtSetErrorHandler ( ctxt , testStructuredErrorHandler , NULL ) ;
2022-11-20 17:36:41 +03:00
xmlCtxtUseOptions ( ctxt , options ) ;
cur = 1 ;
consumed = 0 ;
numCallbacks = 0 ;
avail = 0 ;
while ( ( cur < size ) & & ( numCallbacks < = 1 ) & & ( avail < = 0 ) ) {
int terminate = ( cur + 1 > = size ) ;
int isText = 0 ;
if ( ctxt - > instate = = XML_PARSER_CONTENT ) {
int firstChar = ( ctxt - > input - > end > ctxt - > input - > cur ) ?
* ctxt - > input - > cur :
base [ cur ] ;
if ( ( firstChar ! = ' < ' ) & &
( ( options & XML_PARSE_HTML ) | | ( firstChar ! = ' & ' ) ) )
isText = 1 ;
}
oldConsumed = ctxt - > input - > consumed +
( unsigned long ) ( ctxt - > input - > cur - ctxt - > input - > base ) ;
pushBoundaryCount = 0 ;
pushBoundaryRefCount = 0 ;
pushBoundaryCharsCount = 0 ;
pushBoundaryCDataCount = 0 ;
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML )
htmlParseChunk ( ctxt , base + cur , 1 , terminate ) ;
else
# endif
xmlParseChunk ( ctxt , base + cur , 1 , terminate ) ;
cur + = 1 ;
/*
* Callback check : Check that only a single construct was parsed .
*/
if ( pushBoundaryRefCount > 0 ) {
numCallbacks = 1 ;
} else {
numCallbacks = pushBoundaryCount ;
if ( pushBoundaryCharsCount > 1 ) {
if ( options & XML_PARSE_HTML ) {
/*
* The HTML parser can generate a mix of chars and
* references .
*/
numCallbacks - = pushBoundaryCharsCount - 1 ;
} else {
/*
* Allow two chars callbacks . This can happen when
* multi - byte chars are split across buffer boundaries .
*/
numCallbacks - = 1 ;
}
}
if ( options & XML_PARSE_HTML ) {
/*
* Allow multiple cdata callbacks in HTML mode .
*/
if ( pushBoundaryCDataCount > 1 )
numCallbacks - = pushBoundaryCDataCount - 1 ;
}
}
/*
* Buffer check : If input was consumed , check that the input
* buffer is ( almost ) empty .
*/
consumed = ctxt - > input - > consumed +
( unsigned long ) ( ctxt - > input - > cur - ctxt - > input - > base ) ;
if ( ( ctxt - > instate ! = XML_PARSER_DTD ) & &
( consumed > = 4 ) & &
( consumed ! = oldConsumed ) ) {
size_t max = 0 ;
avail = ctxt - > input - > end - ctxt - > input - > cur ;
if ( ( options & XML_PARSE_HTML ) & &
( ctxt - > instate = = XML_PARSER_END_TAG ) ) {
/* Something related to script parsing. */
max = 3 ;
} else if ( isText ) {
int c = * ctxt - > input - > cur ;
/* 3 bytes for partial UTF-8 */
max = ( ( c = = ' < ' ) | | ( c = = ' & ' ) ) ? 1 : 3 ;
} else if ( ctxt - > instate = = XML_PARSER_CDATA_SECTION ) {
/* 2 bytes for terminator, 3 bytes for UTF-8 */
max = 5 ;
}
if ( avail < = max )
avail = 0 ;
}
}
doc = ctxt - > myDoc ;
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML )
res = 1 ;
else
# endif
res = ctxt - > wellFormed ;
xmlFreeParserCtxt ( ctxt ) ;
free ( ( char * ) base ) ;
if ( numCallbacks > 1 ) {
xmlFreeDoc ( doc ) ;
fprintf ( stderr , " Failed push boundary callback test (%d@%lu-%lu): %s \n " ,
numCallbacks , oldConsumed , consumed , filename ) ;
return ( - 1 ) ;
}
if ( avail > 0 ) {
xmlFreeDoc ( doc ) ;
fprintf ( stderr , " Failed push boundary buffer test (%lu@%lu): %s \n " ,
avail , consumed , filename ) ;
return ( - 1 ) ;
}
if ( ! res ) {
xmlFreeDoc ( doc ) ;
fprintf ( stderr , " Failed to parse %s \n " , filename ) ;
return ( - 1 ) ;
}
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML )
htmlDocDumpMemory ( doc , ( xmlChar * * ) & base , & size ) ;
else
# endif
xmlDocDumpMemory ( doc , ( xmlChar * * ) & base , & size ) ;
xmlFreeDoc ( doc ) ;
res = compareFileMem ( result , base , size ) ;
if ( ( base = = NULL ) | | ( res ! = 0 ) ) {
if ( base ! = NULL )
xmlFree ( ( char * ) base ) ;
fprintf ( stderr , " Result for %s failed in %s \n " , filename , result ) ;
return ( - 1 ) ;
}
xmlFree ( ( char * ) base ) ;
if ( err ! = NULL ) {
res = compareFileMem ( err , testErrors , testErrorsSize ) ;
if ( res ! = 0 ) {
fprintf ( stderr , " Error for %s failed \n " , filename ) ;
return ( - 1 ) ;
}
}
return ( 0 ) ;
}
2005-07-07 00:41:33 +04:00
# endif
/**
* memParseTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages : unused
*
* Parse a file using the old xmlReadMemory API , then serialize back
* reparse the result and serialize again , then check for deviation
* in serialization .
*
* Returns 0 in case of success , an error code otherwise
*/
static int
memParseTest ( const char * filename , const char * result ,
const char * err ATTRIBUTE_UNUSED ,
int options ATTRIBUTE_UNUSED ) {
xmlDocPtr doc ;
const char * base ;
int size , res ;
nb_tests + + ;
/*
* load and parse the memory
*/
if ( loadMem ( filename , & base , & size ) ! = 0 ) {
fprintf ( stderr , " Failed to load %s \n " , filename ) ;
return ( - 1 ) ;
}
2008-08-25 18:53:31 +04:00
2023-12-18 23:41:30 +03:00
doc = xmlReadMemory ( base , size , filename , NULL , XML_PARSE_NOWARNING ) ;
2005-07-07 00:41:33 +04:00
unloadMem ( base ) ;
if ( doc = = NULL ) {
return ( 1 ) ;
}
xmlDocDumpMemory ( doc , ( xmlChar * * ) & base , & size ) ;
xmlFreeDoc ( doc ) ;
res = compareFileMem ( result , base , size ) ;
if ( ( base = = NULL ) | | ( res ! = 0 ) ) {
if ( base ! = NULL )
xmlFree ( ( char * ) base ) ;
2016-05-22 06:14:45 +03:00
fprintf ( stderr , " Result for %s failed in %s \n " , filename , result ) ;
2005-07-07 00:41:33 +04:00
return ( - 1 ) ;
}
xmlFree ( ( char * ) base ) ;
return ( 0 ) ;
}
/**
* noentParseTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages : unused
*
* Parse a file with entity resolution , then serialize back
* reparse the result and serialize again , then check for deviation
* in serialization .
*
* Returns 0 in case of success , an error code otherwise
*/
static int
noentParseTest ( const char * filename , const char * result ,
const char * err ATTRIBUTE_UNUSED ,
int options ) {
xmlDocPtr doc ;
char * temp ;
int res = 0 ;
nb_tests + + ;
/*
* base of the test , parse with the old API
*/
2024-06-07 00:09:17 +03:00
doc = xmlReadFile ( filename , NULL ,
options | XML_PARSE_NOWARNING | XML_PARSE_NOERROR ) ;
2005-07-07 00:41:33 +04:00
if ( doc = = NULL )
return ( 1 ) ;
2020-06-04 12:58:04 +03:00
temp = resultFilename ( filename , temp_directory , " .res " ) ;
2005-07-07 00:41:33 +04:00
if ( temp = = NULL ) {
fprintf ( stderr , " Out of memory \n " ) ;
fatalError ( ) ;
}
xmlSaveFile ( temp , doc ) ;
if ( compareFiles ( temp , result ) ) {
res = 1 ;
}
xmlFreeDoc ( doc ) ;
/*
* Parse the saved result to make sure the round trip is okay
*/
2024-06-07 00:09:17 +03:00
doc = xmlReadFile ( filename , NULL ,
options | XML_PARSE_NOWARNING | XML_PARSE_NOERROR ) ;
2005-07-07 00:41:33 +04:00
if ( doc = = NULL )
return ( 1 ) ;
xmlSaveFile ( temp , doc ) ;
if ( compareFiles ( temp , result ) ) {
res = 1 ;
}
xmlFreeDoc ( doc ) ;
2009-09-05 16:52:55 +04:00
if ( temp ! = NULL ) {
unlink ( temp ) ;
free ( temp ) ;
}
2005-07-07 00:41:33 +04:00
return ( res ) ;
}
/**
* errParseTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file using the xmlReadFile API and check for errors .
*
* Returns 0 in case of success , an error code otherwise
*/
static int
errParseTest ( const char * filename , const char * result , const char * err ,
int options ) {
2023-12-18 23:41:30 +03:00
xmlParserCtxtPtr ctxt ;
2005-07-07 00:41:33 +04:00
xmlDocPtr doc ;
const char * base = NULL ;
int size , res = 0 ;
nb_tests + + ;
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML ) {
2023-12-18 23:41:30 +03:00
ctxt = htmlNewParserCtxt ( ) ;
xmlCtxtSetErrorHandler ( ctxt , testStructuredErrorHandler , NULL ) ;
doc = htmlCtxtReadFile ( ctxt , filename , NULL , options ) ;
htmlFreeParserCtxt ( ctxt ) ;
2005-07-07 00:41:33 +04:00
} else
# endif
2023-12-18 23:41:30 +03:00
{
ctxt = xmlNewParserCtxt ( ) ;
xmlCtxtSetErrorHandler ( ctxt , testStructuredErrorHandler , NULL ) ;
doc = xmlCtxtReadFile ( ctxt , filename , NULL , options ) ;
xmlFreeParserCtxt ( ctxt ) ;
2005-07-07 00:41:33 +04:00
# ifdef LIBXML_XINCLUDE_ENABLED
2023-12-18 23:41:30 +03:00
if ( options & XML_PARSE_XINCLUDE ) {
xmlXIncludeCtxtPtr xinc = NULL ;
xinc = xmlXIncludeNewContext ( doc ) ;
xmlXIncludeSetErrorHandler ( xinc , testStructuredErrorHandler , NULL ) ;
xmlXIncludeSetFlags ( xinc , options ) ;
if ( xmlXIncludeProcessNode ( xinc , ( xmlNodePtr ) doc ) < 0 ) {
testErrorHandler ( NULL , " %s : failed to parse \n " , filename ) ;
xmlFreeDoc ( doc ) ;
doc = NULL ;
}
xmlXIncludeFreeContext ( xinc ) ;
2022-10-22 17:48:58 +03:00
}
2005-07-07 00:41:33 +04:00
# endif
}
if ( result ) {
if ( doc = = NULL ) {
base = " " ;
size = 0 ;
} else {
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML ) {
htmlDocDumpMemory ( doc , ( xmlChar * * ) & base , & size ) ;
} else
# endif
xmlDocDumpMemory ( doc , ( xmlChar * * ) & base , & size ) ;
}
res = compareFileMem ( result , base , size ) ;
}
if ( doc ! = NULL ) {
if ( base ! = NULL )
xmlFree ( ( char * ) base ) ;
xmlFreeDoc ( doc ) ;
}
2020-08-16 23:22:57 +03:00
if ( res ! = 0 ) {
fprintf ( stderr , " Result for %s failed in %s \n " , filename , result ) ;
return ( - 1 ) ;
}
2005-07-07 00:41:33 +04:00
if ( err ! = NULL ) {
res = compareFileMem ( err , testErrors , testErrorsSize ) ;
if ( res ! = 0 ) {
fprintf ( stderr , " Error for %s failed \n " , filename ) ;
return ( - 1 ) ;
}
} else if ( options & XML_PARSE_DTDVALID ) {
if ( testErrorsSize ! = 0 )
fprintf ( stderr , " Validation for %s failed \n " , filename ) ;
}
return ( 0 ) ;
}
2023-09-21 02:29:40 +03:00
# if defined(LIBXML_VALID_ENABLED) || defined(LIBXML_HTML_ENABLED)
2021-08-26 13:50:41 +03:00
/**
* fdParseTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file using the xmlReadFd API and check for errors .
*
* Returns 0 in case of success , an error code otherwise
*/
static int
fdParseTest ( const char * filename , const char * result , const char * err ,
int options ) {
2023-12-18 23:41:30 +03:00
xmlParserCtxtPtr ctxt ;
2021-08-26 13:50:41 +03:00
xmlDocPtr doc ;
const char * base = NULL ;
2022-04-13 17:51:49 +03:00
int size , res = 0 , fd ;
2021-08-26 13:50:41 +03:00
nb_tests + + ;
2022-04-13 17:51:49 +03:00
fd = open ( filename , RD_FLAGS ) ;
2021-08-26 13:50:41 +03:00
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML ) {
2023-12-18 23:41:30 +03:00
ctxt = htmlNewParserCtxt ( ) ;
xmlCtxtSetErrorHandler ( ctxt , testStructuredErrorHandler , NULL ) ;
doc = htmlCtxtReadFd ( ctxt , fd , filename , NULL , options ) ;
htmlFreeParserCtxt ( ctxt ) ;
2021-08-26 13:50:41 +03:00
} else
# endif
{
2023-12-18 23:41:30 +03:00
ctxt = xmlNewParserCtxt ( ) ;
xmlCtxtSetErrorHandler ( ctxt , testStructuredErrorHandler , NULL ) ;
doc = xmlCtxtReadFd ( ctxt , fd , filename , NULL , options ) ;
xmlFreeParserCtxt ( ctxt ) ;
2021-08-26 13:50:41 +03:00
}
close ( fd ) ;
if ( result ) {
if ( doc = = NULL ) {
base = " " ;
size = 0 ;
} else {
# ifdef LIBXML_HTML_ENABLED
if ( options & XML_PARSE_HTML ) {
htmlDocDumpMemory ( doc , ( xmlChar * * ) & base , & size ) ;
} else
# endif
xmlDocDumpMemory ( doc , ( xmlChar * * ) & base , & size ) ;
}
res = compareFileMem ( result , base , size ) ;
}
if ( doc ! = NULL ) {
if ( base ! = NULL )
xmlFree ( ( char * ) base ) ;
xmlFreeDoc ( doc ) ;
}
if ( res ! = 0 ) {
fprintf ( stderr , " Result for %s failed in %s \n " , filename , result ) ;
return ( - 1 ) ;
}
if ( err ! = NULL ) {
res = compareFileMem ( err , testErrors , testErrorsSize ) ;
if ( res ! = 0 ) {
fprintf ( stderr , " Error for %s failed \n " , filename ) ;
return ( - 1 ) ;
}
} else if ( options & XML_PARSE_DTDVALID ) {
if ( testErrorsSize ! = 0 )
fprintf ( stderr , " Validation for %s failed \n " , filename ) ;
}
return ( 0 ) ;
}
2023-09-21 02:29:40 +03:00
# endif
2021-08-26 13:50:41 +03:00
2005-07-07 00:41:33 +04:00
# ifdef LIBXML_READER_ENABLED
/************************************************************************
* *
* Reader based tests *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void processNode ( FILE * out , xmlTextReaderPtr reader ) {
const xmlChar * name , * value ;
int type , empty ;
type = xmlTextReaderNodeType ( reader ) ;
empty = xmlTextReaderIsEmptyElement ( reader ) ;
name = xmlTextReaderConstName ( reader ) ;
if ( name = = NULL )
name = BAD_CAST " -- " ;
value = xmlTextReaderConstValue ( reader ) ;
2008-08-25 18:53:31 +04:00
fprintf ( out , " %d %d %s %d %d " ,
2005-07-07 00:41:33 +04:00
xmlTextReaderDepth ( reader ) ,
type ,
name ,
empty ,
xmlTextReaderHasValue ( reader ) ) ;
if ( value = = NULL )
fprintf ( out , " \n " ) ;
else {
fprintf ( out , " %s \n " , value ) ;
}
}
static int
streamProcessTest ( const char * filename , const char * result , const char * err ,
2017-06-17 15:12:53 +03:00
xmlTextReaderPtr reader , const char * rng ,
int options ATTRIBUTE_UNUSED ) {
2005-07-07 00:41:33 +04:00
int ret ;
char * temp = NULL ;
FILE * t = NULL ;
if ( reader = = NULL )
return ( - 1 ) ;
nb_tests + + ;
if ( result ! = NULL ) {
2020-06-04 12:58:04 +03:00
temp = resultFilename ( filename , temp_directory , " .res " ) ;
2005-07-07 00:41:33 +04:00
if ( temp = = NULL ) {
fprintf ( stderr , " Out of memory \n " ) ;
fatalError ( ) ;
}
t = fopen ( temp , " wb " ) ;
if ( t = = NULL ) {
fprintf ( stderr , " Can't open temp file %s \n " , temp ) ;
free ( temp ) ;
return ( - 1 ) ;
}
}
# ifdef LIBXML_SCHEMAS_ENABLED
if ( rng ! = NULL ) {
ret = xmlTextReaderRelaxNGValidate ( reader , rng ) ;
if ( ret < 0 ) {
testErrorHandler ( NULL , " Relax-NG schema %s failed to compile \n " ,
rng ) ;
fclose ( t ) ;
2009-09-05 16:52:55 +04:00
if ( temp ! = NULL ) {
unlink ( temp ) ;
free ( temp ) ;
}
2005-07-07 00:41:33 +04:00
return ( 0 ) ;
}
}
# endif
ret = xmlTextReaderRead ( reader ) ;
while ( ret = = 1 ) {
if ( ( t ! = NULL ) & & ( rng = = NULL ) )
processNode ( t , reader ) ;
ret = xmlTextReaderRead ( reader ) ;
}
if ( ret ! = 0 ) {
testErrorHandler ( NULL , " %s : failed to parse \n " , filename ) ;
}
if ( rng ! = NULL ) {
if ( xmlTextReaderIsValid ( reader ) ! = 1 ) {
testErrorHandler ( NULL , " %s fails to validate \n " , filename ) ;
} else {
testErrorHandler ( NULL , " %s validates \n " , filename ) ;
}
}
if ( t ! = NULL ) {
fclose ( t ) ;
ret = compareFiles ( temp , result ) ;
2009-09-05 16:52:55 +04:00
if ( temp ! = NULL ) {
unlink ( temp ) ;
free ( temp ) ;
}
2005-07-07 00:41:33 +04:00
if ( ret ) {
2016-05-22 06:14:45 +03:00
fprintf ( stderr , " Result for %s failed in %s \n " , filename , result ) ;
2005-07-07 00:41:33 +04:00
return ( - 1 ) ;
}
}
if ( err ! = NULL ) {
ret = compareFileMem ( err , testErrors , testErrorsSize ) ;
if ( ret ! = 0 ) {
fprintf ( stderr , " Error for %s failed \n " , filename ) ;
printf ( " %s " , testErrors ) ;
return ( - 1 ) ;
}
}
return ( 0 ) ;
}
/**
* streamParseTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file using the reader API and check for errors .
*
* Returns 0 in case of success , an error code otherwise
*/
static int
streamParseTest ( const char * filename , const char * result , const char * err ,
int options ) {
xmlTextReaderPtr reader ;
int ret ;
reader = xmlReaderForFile ( filename , NULL , options ) ;
2023-12-18 23:41:30 +03:00
xmlTextReaderSetStructuredErrorHandler ( reader , testStructuredErrorHandler ,
NULL ) ;
2012-10-25 11:39:39 +04:00
ret = streamProcessTest ( filename , result , err , reader , NULL , options ) ;
2005-07-07 00:41:33 +04:00
xmlFreeTextReader ( reader ) ;
return ( ret ) ;
}
/**
* walkerParseTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file using the walker , i . e . a reader built from a atree .
*
* Returns 0 in case of success , an error code otherwise
*/
static int
walkerParseTest ( const char * filename , const char * result , const char * err ,
int options ) {
xmlDocPtr doc ;
xmlTextReaderPtr reader ;
int ret ;
2023-12-18 23:41:30 +03:00
doc = xmlReadFile ( filename , NULL , options | XML_PARSE_NOWARNING ) ;
2005-07-07 00:41:33 +04:00
if ( doc = = NULL ) {
fprintf ( stderr , " Failed to parse %s \n " , filename ) ;
return ( - 1 ) ;
}
reader = xmlReaderWalker ( doc ) ;
2012-10-25 11:39:39 +04:00
ret = streamProcessTest ( filename , result , err , reader , NULL , options ) ;
2005-07-07 00:41:33 +04:00
xmlFreeTextReader ( reader ) ;
xmlFreeDoc ( doc ) ;
return ( ret ) ;
}
/**
* streamMemParseTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file using the reader API from memory and check for errors .
*
* Returns 0 in case of success , an error code otherwise
*/
static int
streamMemParseTest ( const char * filename , const char * result , const char * err ,
int options ) {
xmlTextReaderPtr reader ;
int ret ;
const char * base ;
int size ;
/*
* load and parse the memory
*/
if ( loadMem ( filename , & base , & size ) ! = 0 ) {
fprintf ( stderr , " Failed to load %s \n " , filename ) ;
return ( - 1 ) ;
}
reader = xmlReaderForMemory ( base , size , filename , NULL , options ) ;
2023-12-18 23:41:30 +03:00
xmlTextReaderSetStructuredErrorHandler ( reader , testStructuredErrorHandler ,
NULL ) ;
2012-10-25 11:39:39 +04:00
ret = streamProcessTest ( filename , result , err , reader , NULL , options ) ;
2005-07-07 00:41:33 +04:00
free ( ( char * ) base ) ;
xmlFreeTextReader ( reader ) ;
return ( ret ) ;
}
# endif
# ifdef LIBXML_XPATH_ENABLED
# ifdef LIBXML_DEBUG_ENABLED
/************************************************************************
* *
* XPath and XPointer based tests *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-07-29 03:49:35 +04:00
static FILE * xpathOutput ;
static xmlDocPtr xpathDocument ;
2005-07-07 00:41:33 +04:00
static void
testXPath ( const char * str , int xptr , int expr ) {
xmlXPathObjectPtr res ;
xmlXPathContextPtr ctxt ;
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
nb_tests + + ;
# if defined(LIBXML_XPTR_ENABLED)
if ( xptr ) {
2024-06-12 19:20:01 +03:00
ctxt = xmlXPathNewContext ( xpathDocument ) ;
2023-12-18 23:41:30 +03:00
xmlXPathSetErrorHandler ( ctxt , testStructuredErrorHandler , NULL ) ;
2005-07-07 00:41:33 +04:00
res = xmlXPtrEval ( BAD_CAST str , ctxt ) ;
} else {
# endif
ctxt = xmlXPathNewContext ( xpathDocument ) ;
2023-12-18 23:41:30 +03:00
xmlXPathSetErrorHandler ( ctxt , testStructuredErrorHandler , NULL ) ;
2005-07-07 00:41:33 +04:00
ctxt - > node = xmlDocGetRootElement ( xpathDocument ) ;
if ( expr )
res = xmlXPathEvalExpression ( BAD_CAST str , ctxt ) ;
else {
/* res = xmlXPathEval(BAD_CAST str, ctxt); */
xmlXPathCompExprPtr comp ;
comp = xmlXPathCompile ( BAD_CAST str ) ;
if ( comp ! = NULL ) {
res = xmlXPathCompiledEval ( comp , ctxt ) ;
xmlXPathFreeCompExpr ( comp ) ;
} else
res = NULL ;
}
# if defined(LIBXML_XPTR_ENABLED)
}
# endif
xmlXPathDebugDumpObject ( xpathOutput , res , 0 ) ;
xmlXPathFreeObject ( res ) ;
xmlXPathFreeContext ( ctxt ) ;
}
/**
* xpathExprTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file containing XPath standalone expressions and evaluate them
*
* Returns 0 in case of success , an error code otherwise
*/
static int
xpathCommonTest ( const char * filename , const char * result ,
int xptr , int expr ) {
FILE * input ;
char expression [ 5000 ] ;
int len , ret = 0 ;
char * temp ;
2020-06-04 12:58:04 +03:00
temp = resultFilename ( filename , temp_directory , " .res " ) ;
2005-07-07 00:41:33 +04:00
if ( temp = = NULL ) {
fprintf ( stderr , " Out of memory \n " ) ;
fatalError ( ) ;
}
xpathOutput = fopen ( temp , " wb " ) ;
if ( xpathOutput = = NULL ) {
fprintf ( stderr , " failed to open output file %s \n " , temp ) ;
free ( temp ) ;
return ( - 1 ) ;
}
input = fopen ( filename , " rb " ) ;
if ( input = = NULL ) {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2005-07-07 00:41:33 +04:00
" Cannot open %s for reading \n " , filename ) ;
free ( temp ) ;
return ( - 1 ) ;
}
while ( fgets ( expression , 4500 , input ) ! = NULL ) {
len = strlen ( expression ) ;
len - - ;
2008-08-25 18:53:31 +04:00
while ( ( len > = 0 ) & &
2005-07-07 00:41:33 +04:00
( ( expression [ len ] = = ' \n ' ) | | ( expression [ len ] = = ' \t ' ) | |
( expression [ len ] = = ' \r ' ) | | ( expression [ len ] = = ' ' ) ) ) len - - ;
2008-08-25 18:53:31 +04:00
expression [ len + 1 ] = 0 ;
2005-07-07 00:41:33 +04:00
if ( len > = 0 ) {
fprintf ( xpathOutput ,
" \n ======================== \n Expression: %s \n " ,
expression ) ;
testXPath ( expression , xptr , expr ) ;
}
}
fclose ( input ) ;
fclose ( xpathOutput ) ;
if ( result ! = NULL ) {
ret = compareFiles ( temp , result ) ;
if ( ret ) {
2016-05-22 06:14:45 +03:00
fprintf ( stderr , " Result for %s failed in %s \n " , filename , result ) ;
2005-07-07 00:41:33 +04:00
}
}
2009-09-05 16:52:55 +04:00
if ( temp ! = NULL ) {
unlink ( temp ) ;
free ( temp ) ;
}
2005-07-07 00:41:33 +04:00
return ( ret ) ;
}
/**
* xpathExprTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file containing XPath standalone expressions and evaluate them
*
* Returns 0 in case of success , an error code otherwise
*/
static int
xpathExprTest ( const char * filename , const char * result ,
const char * err ATTRIBUTE_UNUSED ,
int options ATTRIBUTE_UNUSED ) {
return ( xpathCommonTest ( filename , result , 0 , 1 ) ) ;
}
/**
* xpathDocTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file containing XPath expressions and evaluate them against
* a set of corresponding documents .
*
* Returns 0 in case of success , an error code otherwise
*/
static int
xpathDocTest ( const char * filename ,
const char * resul ATTRIBUTE_UNUSED ,
const char * err ATTRIBUTE_UNUSED ,
int options ) {
char pattern [ 500 ] ;
char result [ 500 ] ;
glob_t globbuf ;
size_t i ;
int ret = 0 , res ;
xpathDocument = xmlReadFile ( filename , NULL ,
options | XML_PARSE_DTDATTR | XML_PARSE_NOENT ) ;
if ( xpathDocument = = NULL ) {
fprintf ( stderr , " Failed to load %s \n " , filename ) ;
return ( - 1 ) ;
}
2019-01-01 18:30:38 +03:00
res = snprintf ( pattern , 499 , " ./test/XPath/tests/%s* " ,
baseFilename ( filename ) ) ;
if ( res > = 499 )
pattern [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
globbuf . gl_offs = 0 ;
glob ( pattern , GLOB_DOOFFS , NULL , & globbuf ) ;
for ( i = 0 ; i < globbuf . gl_pathc ; i + + ) {
2019-01-01 18:30:38 +03:00
res = snprintf ( result , 499 , " result/XPath/tests/%s " ,
2005-07-07 00:41:33 +04:00
baseFilename ( globbuf . gl_pathv [ i ] ) ) ;
2019-01-01 18:30:38 +03:00
if ( res > = 499 )
result [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
res = xpathCommonTest ( globbuf . gl_pathv [ i ] , & result [ 0 ] , 0 , 0 ) ;
if ( res ! = 0 )
ret = res ;
}
globfree ( & globbuf ) ;
xmlFreeDoc ( xpathDocument ) ;
return ( ret ) ;
}
2022-04-21 04:52:52 +03:00
# ifdef LIBXML_XPTR_ENABLED
2005-07-07 00:41:33 +04:00
/**
* xptrDocTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file containing XPath expressions and evaluate them against
* a set of corresponding documents .
*
* Returns 0 in case of success , an error code otherwise
*/
static int
xptrDocTest ( const char * filename ,
const char * resul ATTRIBUTE_UNUSED ,
const char * err ATTRIBUTE_UNUSED ,
2024-06-12 19:20:01 +03:00
int options ATTRIBUTE_UNUSED ) {
2005-07-07 00:41:33 +04:00
char pattern [ 500 ] ;
char result [ 500 ] ;
glob_t globbuf ;
size_t i ;
int ret = 0 , res ;
xpathDocument = xmlReadFile ( filename , NULL ,
2022-04-21 04:52:52 +03:00
XML_PARSE_DTDATTR | XML_PARSE_NOENT ) ;
2005-07-07 00:41:33 +04:00
if ( xpathDocument = = NULL ) {
fprintf ( stderr , " Failed to load %s \n " , filename ) ;
return ( - 1 ) ;
}
2024-06-12 19:20:01 +03:00
res = snprintf ( pattern , 499 , " ./test/XPath/xptr/%s* " ,
baseFilename ( filename ) ) ;
2019-01-01 18:30:38 +03:00
if ( res > = 499 )
pattern [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
globbuf . gl_offs = 0 ;
glob ( pattern , GLOB_DOOFFS , NULL , & globbuf ) ;
for ( i = 0 ; i < globbuf . gl_pathc ; i + + ) {
2024-06-12 19:20:01 +03:00
res = snprintf ( result , 499 , " result/XPath/xptr/%s " ,
baseFilename ( globbuf . gl_pathv [ i ] ) ) ;
2019-01-01 18:30:38 +03:00
if ( res > = 499 )
result [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
res = xpathCommonTest ( globbuf . gl_pathv [ i ] , & result [ 0 ] , 1 , 0 ) ;
if ( res ! = 0 )
ret = res ;
}
globfree ( & globbuf ) ;
xmlFreeDoc ( xpathDocument ) ;
return ( ret ) ;
}
# endif /* LIBXML_XPTR_ENABLED */
2022-02-22 13:52:38 +03:00
# ifdef LIBXML_VALID_ENABLED
2005-07-07 00:41:33 +04:00
/**
* xmlidDocTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file containing xml : id and check for errors and verify
* that XPath queries will work on them as expected .
*
* Returns 0 in case of success , an error code otherwise
*/
static int
xmlidDocTest ( const char * filename ,
const char * result ,
const char * err ,
int options ) {
2023-12-18 23:41:30 +03:00
xmlParserCtxtPtr ctxt ;
2005-07-07 00:41:33 +04:00
int res = 0 ;
int ret = 0 ;
char * temp ;
2023-12-18 23:41:30 +03:00
ctxt = xmlNewParserCtxt ( ) ;
xmlCtxtSetErrorHandler ( ctxt , testStructuredErrorHandler , NULL ) ;
xpathDocument = xmlCtxtReadFile ( ctxt , filename , NULL ,
options | XML_PARSE_DTDATTR | XML_PARSE_NOENT ) ;
xmlFreeParserCtxt ( ctxt ) ;
2005-07-07 00:41:33 +04:00
if ( xpathDocument = = NULL ) {
fprintf ( stderr , " Failed to load %s \n " , filename ) ;
return ( - 1 ) ;
}
2020-06-04 12:58:04 +03:00
temp = resultFilename ( filename , temp_directory , " .res " ) ;
2005-07-07 00:41:33 +04:00
if ( temp = = NULL ) {
fprintf ( stderr , " Out of memory \n " ) ;
fatalError ( ) ;
}
xpathOutput = fopen ( temp , " wb " ) ;
if ( xpathOutput = = NULL ) {
fprintf ( stderr , " failed to open output file %s \n " , temp ) ;
xmlFreeDoc ( xpathDocument ) ;
free ( temp ) ;
return ( - 1 ) ;
}
testXPath ( " id('bar') " , 0 , 0 ) ;
fclose ( xpathOutput ) ;
if ( result ! = NULL ) {
ret = compareFiles ( temp , result ) ;
if ( ret ) {
2016-05-22 06:14:45 +03:00
fprintf ( stderr , " Result for %s failed in %s \n " , filename , result ) ;
2005-07-07 00:41:33 +04:00
res = 1 ;
}
}
2009-09-05 16:52:55 +04:00
if ( temp ! = NULL ) {
unlink ( temp ) ;
free ( temp ) ;
}
2005-07-07 00:41:33 +04:00
xmlFreeDoc ( xpathDocument ) ;
if ( err ! = NULL ) {
ret = compareFileMem ( err , testErrors , testErrorsSize ) ;
if ( ret ! = 0 ) {
fprintf ( stderr , " Error for %s failed \n " , filename ) ;
res = 1 ;
}
}
return ( res ) ;
}
2022-02-22 13:52:38 +03:00
# endif /* LIBXML_VALID_ENABLED */
2005-07-07 00:41:33 +04:00
# endif /* LIBXML_DEBUG_ENABLED */
# endif /* XPATH */
/************************************************************************
* *
* URI based tests *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void
handleURI ( const char * str , const char * base , FILE * o ) {
int ret ;
xmlURIPtr uri ;
2006-03-10 03:36:23 +03:00
xmlChar * res = NULL ;
2005-07-07 00:41:33 +04:00
uri = xmlCreateURI ( ) ;
if ( base = = NULL ) {
ret = xmlParseURIReference ( uri , str ) ;
if ( ret ! = 0 )
fprintf ( o , " %s : error %d \n " , str , ret ) ;
else {
xmlNormalizeURIPath ( uri - > path ) ;
xmlPrintURI ( o , uri ) ;
fprintf ( o , " \n " ) ;
}
} else {
res = xmlBuildURI ( ( xmlChar * ) str , ( xmlChar * ) base ) ;
if ( res ! = NULL ) {
fprintf ( o , " %s \n " , ( char * ) res ) ;
}
else
fprintf ( o , " ::ERROR:: \n " ) ;
}
if ( res ! = NULL )
xmlFree ( res ) ;
xmlFreeURI ( uri ) ;
}
/**
* uriCommonTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file containing URI and check for errors
*
* Returns 0 in case of success , an error code otherwise
*/
static int
uriCommonTest ( const char * filename ,
const char * result ,
const char * err ,
const char * base ) {
char * temp ;
FILE * o , * f ;
char str [ 1024 ] ;
int res = 0 , i , ret ;
2020-06-04 12:58:04 +03:00
temp = resultFilename ( filename , temp_directory , " .res " ) ;
2005-07-07 00:41:33 +04:00
if ( temp = = NULL ) {
fprintf ( stderr , " Out of memory \n " ) ;
fatalError ( ) ;
}
o = fopen ( temp , " wb " ) ;
if ( o = = NULL ) {
fprintf ( stderr , " failed to open output file %s \n " , temp ) ;
free ( temp ) ;
return ( - 1 ) ;
}
f = fopen ( filename , " rb " ) ;
if ( f = = NULL ) {
fprintf ( stderr , " failed to open input file %s \n " , filename ) ;
fclose ( o ) ;
2009-09-05 16:52:55 +04:00
if ( temp ! = NULL ) {
unlink ( temp ) ;
free ( temp ) ;
}
2005-07-07 00:41:33 +04:00
return ( - 1 ) ;
}
while ( 1 ) {
/*
* read one line in string buffer .
*/
if ( fgets ( & str [ 0 ] , sizeof ( str ) - 1 , f ) = = NULL )
break ;
/*
* remove the ending spaces
*/
i = strlen ( str ) ;
while ( ( i > 0 ) & &
( ( str [ i - 1 ] = = ' \n ' ) | | ( str [ i - 1 ] = = ' \r ' ) | |
( str [ i - 1 ] = = ' ' ) | | ( str [ i - 1 ] = = ' \t ' ) ) ) {
i - - ;
str [ i ] = 0 ;
}
nb_tests + + ;
handleURI ( str , base , o ) ;
}
fclose ( f ) ;
fclose ( o ) ;
if ( result ! = NULL ) {
ret = compareFiles ( temp , result ) ;
if ( ret ) {
2016-05-22 06:14:45 +03:00
fprintf ( stderr , " Result for %s failed in %s \n " , filename , result ) ;
2005-07-07 00:41:33 +04:00
res = 1 ;
}
}
if ( err ! = NULL ) {
ret = compareFileMem ( err , testErrors , testErrorsSize ) ;
if ( ret ! = 0 ) {
fprintf ( stderr , " Error for %s failed \n " , filename ) ;
res = 1 ;
}
}
2009-09-05 16:52:55 +04:00
if ( temp ! = NULL ) {
unlink ( temp ) ;
free ( temp ) ;
}
2005-07-07 00:41:33 +04:00
return ( res ) ;
}
/**
* uriParseTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file containing URI and check for errors
*
* Returns 0 in case of success , an error code otherwise
*/
static int
uriParseTest ( const char * filename ,
const char * result ,
const char * err ,
int options ATTRIBUTE_UNUSED ) {
return ( uriCommonTest ( filename , result , err , NULL ) ) ;
}
/**
* uriBaseTest :
* @ filename : the file to parse
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file containing URI , compose them against a fixed base and
* check for errors
*
* Returns 0 in case of success , an error code otherwise
*/
static int
uriBaseTest ( const char * filename ,
const char * result ,
const char * err ,
int options ATTRIBUTE_UNUSED ) {
return ( uriCommonTest ( filename , result , err ,
" http://foo.com/path/to/index.html?orig#help " ) ) ;
}
2005-08-07 14:46:19 +04:00
static int urip_success = 1 ;
static int urip_current = 0 ;
static const char * urip_testURLs [ ] = {
" urip://example.com/a b.html " ,
" urip://example.com/a%20b.html " ,
" file:///path/to/a b.html " ,
" file:///path/to/a%20b.html " ,
" /path/to/a b.html " ,
" /path/to/a%20b.html " ,
2012-08-20 16:58:24 +04:00
" urip://example.com/r " " \xe9 " " sum " " \xe9 " " .html " ,
2005-08-07 14:46:19 +04:00
" urip://example.com/test?a=1&b=2%263&c=4#foo " ,
NULL
} ;
static const char * urip_rcvsURLs [ ] = {
/* it is an URI the strings must be escaped */
" urip://example.com/a%20b.html " ,
/* check that % escaping is not broken */
" urip://example.com/a%20b.html " ,
/* it's an URI path the strings must be escaped */
" file:///path/to/a%20b.html " ,
/* check that % escaping is not broken */
" file:///path/to/a%20b.html " ,
/* this is not an URI, this is a path, so this should not be escaped */
" /path/to/a b.html " ,
/* check that paths with % are not broken */
" /path/to/a%20b.html " ,
/* out of context the encoding can't be guessed byte by byte conversion */
" urip://example.com/r%E9sum%E9.html " ,
/* verify we don't destroy URIs especially the query part */
" urip://example.com/test?a=1&b=2%263&c=4#foo " ,
NULL
} ;
static const char * urip_res = " <list/> " ;
static const char * urip_cur = NULL ;
static int urip_rlen ;
/**
* uripMatch :
* @ URI : an URI to test
*
* Check for an urip : query
*
* Returns 1 if yes and 0 if another Input module should be used
*/
static int
uripMatch ( const char * URI ) {
2022-03-30 01:32:35 +03:00
if ( ( URI = = NULL ) | | ( ! strcmp ( URI , " file:// " SYSCONFDIR " /xml/catalog " ) ) )
2005-08-07 14:46:19 +04:00
return ( 0 ) ;
/* Verify we received the escaped URL */
if ( strcmp ( urip_rcvsURLs [ urip_current ] , URI ) )
urip_success = 0 ;
return ( 1 ) ;
}
/**
* uripOpen :
* @ URI : an URI to test
*
* Return a pointer to the urip : query handler , in this example simply
* the urip_current pointer . . .
*
* Returns an Input context or NULL in case or error
*/
static void *
uripOpen ( const char * URI ) {
2022-03-30 01:32:35 +03:00
if ( ( URI = = NULL ) | | ( ! strcmp ( URI , " file:// " SYSCONFDIR " /xml/catalog " ) ) )
2005-08-07 14:46:19 +04:00
return ( NULL ) ;
/* Verify we received the escaped URL */
if ( strcmp ( urip_rcvsURLs [ urip_current ] , URI ) )
urip_success = 0 ;
urip_cur = urip_res ;
urip_rlen = strlen ( urip_res ) ;
return ( ( void * ) urip_cur ) ;
}
/**
* uripClose :
* @ context : the read context
*
* Close the urip : query handler
*
* Returns 0 or - 1 in case of error
*/
static int
uripClose ( void * context ) {
if ( context = = NULL ) return ( - 1 ) ;
urip_cur = NULL ;
urip_rlen = 0 ;
return ( 0 ) ;
}
/**
* uripRead :
* @ context : the read context
* @ buffer : where to store data
* @ len : number of bytes to read
*
* Implement an urip : query read .
*
* Returns the number of bytes read or - 1 in case of error
*/
static int
uripRead ( void * context , char * buffer , int len ) {
const char * ptr = ( const char * ) context ;
if ( ( context = = NULL ) | | ( buffer = = NULL ) | | ( len < 0 ) )
return ( - 1 ) ;
if ( len > urip_rlen ) len = urip_rlen ;
memcpy ( buffer , ptr , len ) ;
urip_rlen - = len ;
return ( len ) ;
}
static int
urip_checkURL ( const char * URL ) {
xmlDocPtr doc ;
doc = xmlReadFile ( URL , NULL , 0 ) ;
if ( doc = = NULL )
return ( - 1 ) ;
xmlFreeDoc ( doc ) ;
return ( 1 ) ;
}
/**
* uriPathTest :
* @ filename : ignored
* @ result : ignored
* @ err : ignored
*
* Run a set of tests to check how Path and URI are handled before
* being passed to the I / O layer
*
* Returns 0 in case of success , an error code otherwise
*/
static int
uriPathTest ( const char * filename ATTRIBUTE_UNUSED ,
const char * result ATTRIBUTE_UNUSED ,
const char * err ATTRIBUTE_UNUSED ,
int options ATTRIBUTE_UNUSED ) {
int parsed ;
int failures = 0 ;
/*
* register the new I / O handlers
*/
if ( xmlRegisterInputCallbacks ( uripMatch , uripOpen , uripRead , uripClose ) < 0 )
{
fprintf ( stderr , " failed to register HTTP handler \n " ) ;
return ( - 1 ) ;
}
for ( urip_current = 0 ; urip_testURLs [ urip_current ] ! = NULL ; urip_current + + ) {
urip_success = 1 ;
parsed = urip_checkURL ( urip_testURLs [ urip_current ] ) ;
if ( urip_success ! = 1 ) {
fprintf ( stderr , " failed the URL passing test for %s " ,
urip_testURLs [ urip_current ] ) ;
failures + + ;
} else if ( parsed ! = 1 ) {
fprintf ( stderr , " failed the parsing test for %s " ,
urip_testURLs [ urip_current ] ) ;
failures + + ;
}
nb_tests + + ;
}
xmlPopInputCallbacks ( ) ;
return ( failures ) ;
}
2005-07-07 00:41:33 +04:00
# ifdef LIBXML_SCHEMAS_ENABLED
/************************************************************************
* *
* Schemas tests *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int
schemasOneTest ( const char * sch ,
const char * filename ,
const char * result ,
2023-04-30 22:26:55 +03:00
const char * err ,
2005-07-07 00:41:33 +04:00
int options ,
xmlSchemaPtr schemas ) {
int ret = 0 ;
2023-04-30 22:26:55 +03:00
int i ;
2005-07-07 00:41:33 +04:00
char * temp ;
2023-04-30 22:26:55 +03:00
int parseErrorsSize = testErrorsSize ;
2005-07-07 00:41:33 +04:00
2020-06-04 12:58:04 +03:00
temp = resultFilename ( result , temp_directory , " .res " ) ;
2005-07-07 00:41:33 +04:00
if ( temp = = NULL ) {
fprintf ( stderr , " Out of memory \n " ) ;
fatalError ( ) ;
2023-04-30 22:26:55 +03:00
return ( - 1 ) ;
2005-07-07 00:41:33 +04:00
}
2023-04-30 22:26:55 +03:00
/*
* Test both memory and streaming validation .
*/
for ( i = 0 ; i < 2 ; i + + ) {
xmlSchemaValidCtxtPtr ctxt ;
int validResult = 0 ;
FILE * schemasOutput ;
testErrorsSize = parseErrorsSize ;
testErrors [ parseErrorsSize ] = 0 ;
2024-01-04 04:48:02 +03:00
if ( schemas = = NULL )
goto done ;
2023-04-30 22:26:55 +03:00
ctxt = xmlSchemaNewValidCtxt ( schemas ) ;
2023-12-18 23:41:30 +03:00
xmlSchemaSetValidStructuredErrors ( ctxt , testStructuredErrorHandler ,
NULL ) ;
2023-04-30 22:26:55 +03:00
schemasOutput = fopen ( temp , " wb " ) ;
if ( schemasOutput = = NULL ) {
fprintf ( stderr , " failed to open output file %s \n " , temp ) ;
free ( temp ) ;
return ( - 1 ) ;
}
if ( i = = 0 ) {
xmlDocPtr doc ;
doc = xmlReadFile ( filename , NULL , options ) ;
if ( doc = = NULL ) {
fprintf ( stderr , " failed to parse instance %s for %s \n " , filename , sch ) ;
return ( - 1 ) ;
}
validResult = xmlSchemaValidateDoc ( ctxt , doc ) ;
xmlFreeDoc ( doc ) ;
} else {
validResult = xmlSchemaValidateFile ( ctxt , filename , options ) ;
}
if ( validResult = = 0 ) {
fprintf ( schemasOutput , " %s validates \n " , filename ) ;
} else if ( validResult > 0 ) {
fprintf ( schemasOutput , " %s fails to validate \n " , filename ) ;
} else {
fprintf ( schemasOutput , " %s validation generated an internal error \n " ,
filename ) ;
}
fclose ( schemasOutput ) ;
2024-01-04 04:48:02 +03:00
2023-04-30 22:26:55 +03:00
if ( result ) {
if ( compareFiles ( temp , result ) ) {
fprintf ( stderr , " Result for %s on %s failed \n " , filename , sch ) ;
ret = 1 ;
}
}
2024-01-04 04:48:02 +03:00
xmlSchemaFreeValidCtxt ( ctxt ) ;
done :
2023-04-30 22:26:55 +03:00
if ( compareFileMem ( err , testErrors , testErrorsSize ) ) {
fprintf ( stderr , " Error for %s on %s failed \n " , filename , sch ) ;
ret = 1 ;
}
2009-09-05 16:52:55 +04:00
unlink ( temp ) ;
}
2005-07-07 00:41:33 +04:00
2023-04-30 22:26:55 +03:00
free ( temp ) ;
2005-07-07 00:41:33 +04:00
return ( ret ) ;
}
/**
* schemasTest :
* @ filename : the schemas file
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse a file containing URI , compose them against a fixed base and
* check for errors
*
* Returns 0 in case of success , an error code otherwise
*/
static int
schemasTest ( const char * filename ,
const char * resul ATTRIBUTE_UNUSED ,
const char * errr ATTRIBUTE_UNUSED ,
int options ) {
const char * base = baseFilename ( filename ) ;
const char * base2 ;
const char * instance ;
xmlSchemaParserCtxtPtr ctxt ;
xmlSchemaPtr schemas ;
int res = 0 , len , ret ;
2022-04-04 04:12:49 +03:00
int parseErrorsSize ;
2005-07-07 00:41:33 +04:00
char pattern [ 500 ] ;
char prefix [ 500 ] ;
char result [ 500 ] ;
char err [ 500 ] ;
glob_t globbuf ;
size_t i ;
char count = 0 ;
/* first compile the schemas if possible */
ctxt = xmlSchemaNewParserCtxt ( filename ) ;
2023-12-18 23:41:30 +03:00
xmlSchemaSetParserStructuredErrors ( ctxt , testStructuredErrorHandler , NULL ) ;
2005-07-07 00:41:33 +04:00
schemas = xmlSchemaParse ( ctxt ) ;
xmlSchemaFreeParserCtxt ( ctxt ) ;
2022-04-04 04:12:49 +03:00
parseErrorsSize = testErrorsSize ;
2005-07-07 00:41:33 +04:00
/*
* most of the mess is about the output filenames generated by the Makefile
*/
len = strlen ( base ) ;
if ( ( len > 499 ) | | ( len < 5 ) ) {
xmlSchemaFree ( schemas ) ;
return ( - 1 ) ;
}
len - = 4 ; /* remove trailing .xsd */
if ( base [ len - 2 ] = = ' _ ' ) {
len - = 2 ; /* remove subtest number */
}
if ( base [ len - 2 ] = = ' _ ' ) {
len - = 2 ; /* remove subtest number */
}
memcpy ( prefix , base , len ) ;
prefix [ len ] = 0 ;
2022-04-04 04:12:49 +03:00
if ( snprintf ( pattern , 499 , " ./test/schemas/%s_*.xml " , prefix ) > = 499 )
2019-01-01 18:30:38 +03:00
pattern [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
if ( base [ len ] = = ' _ ' ) {
len + = 2 ;
memcpy ( prefix , base , len ) ;
prefix [ len ] = 0 ;
}
globbuf . gl_offs = 0 ;
glob ( pattern , GLOB_DOOFFS , NULL , & globbuf ) ;
for ( i = 0 ; i < globbuf . gl_pathc ; i + + ) {
2022-04-04 04:12:49 +03:00
testErrorsSize = parseErrorsSize ;
testErrors [ parseErrorsSize ] = 0 ;
2005-07-07 00:41:33 +04:00
instance = globbuf . gl_pathv [ i ] ;
base2 = baseFilename ( instance ) ;
len = strlen ( base2 ) ;
if ( ( len > 6 ) & & ( base2 [ len - 6 ] = = ' _ ' ) ) {
count = base2 [ len - 5 ] ;
2019-01-01 18:30:38 +03:00
ret = snprintf ( result , 499 , " result/schemas/%s_%c " ,
2005-07-07 00:41:33 +04:00
prefix , count ) ;
2019-01-01 18:30:38 +03:00
if ( ret > = 499 )
result [ 499 ] = 0 ;
ret = snprintf ( err , 499 , " result/schemas/%s_%c.err " ,
2005-07-07 00:41:33 +04:00
prefix , count ) ;
2019-01-01 18:30:38 +03:00
if ( ret > = 499 )
err [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
} else {
fprintf ( stderr , " don't know how to process %s \n " , instance ) ;
continue ;
}
2024-01-04 04:48:02 +03:00
nb_tests + + ;
ret = schemasOneTest ( filename , instance , result , err ,
options , schemas ) ;
if ( ret ! = 0 )
res = ret ;
2005-07-07 00:41:33 +04:00
}
globfree ( & globbuf ) ;
xmlSchemaFree ( schemas ) ;
return ( res ) ;
}
/************************************************************************
* *
* Schemas tests *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int
rngOneTest ( const char * sch ,
const char * filename ,
const char * result ,
int options ,
xmlRelaxNGPtr schemas ) {
xmlDocPtr doc ;
xmlRelaxNGValidCtxtPtr ctxt ;
int ret = 0 ;
char * temp ;
FILE * schemasOutput ;
doc = xmlReadFile ( filename , NULL , options ) ;
if ( doc = = NULL ) {
fprintf ( stderr , " failed to parse instance %s for %s \n " , filename , sch ) ;
return ( - 1 ) ;
}
2020-06-04 12:58:04 +03:00
temp = resultFilename ( result , temp_directory , " .res " ) ;
2005-07-07 00:41:33 +04:00
if ( temp = = NULL ) {
fprintf ( stderr , " Out of memory \n " ) ;
fatalError ( ) ;
}
schemasOutput = fopen ( temp , " wb " ) ;
if ( schemasOutput = = NULL ) {
fprintf ( stderr , " failed to open output file %s \n " , temp ) ;
xmlFreeDoc ( doc ) ;
free ( temp ) ;
return ( - 1 ) ;
}
ctxt = xmlRelaxNGNewValidCtxt ( schemas ) ;
2023-12-18 23:41:30 +03:00
xmlRelaxNGSetValidStructuredErrors ( ctxt , testStructuredErrorHandler , NULL ) ;
2005-07-07 00:41:33 +04:00
ret = xmlRelaxNGValidateDoc ( ctxt , doc ) ;
if ( ret = = 0 ) {
testErrorHandler ( NULL , " %s validates \n " , filename ) ;
} else if ( ret > 0 ) {
testErrorHandler ( NULL , " %s fails to validate \n " , filename ) ;
} else {
testErrorHandler ( NULL , " %s validation generated an internal error \n " ,
filename ) ;
}
fclose ( schemasOutput ) ;
2009-09-07 16:58:47 +04:00
ret = 0 ;
2005-07-07 00:41:33 +04:00
if ( result ) {
if ( compareFiles ( temp , result ) ) {
fprintf ( stderr , " Result for %s on %s failed \n " , filename , sch ) ;
ret = 1 ;
}
}
2009-09-05 16:52:55 +04:00
if ( temp ! = NULL ) {
unlink ( temp ) ;
free ( temp ) ;
}
2005-07-07 00:41:33 +04:00
xmlRelaxNGFreeValidCtxt ( ctxt ) ;
xmlFreeDoc ( doc ) ;
return ( ret ) ;
}
/**
* rngTest :
* @ filename : the schemas file
* @ result : the file with expected result
* @ err : the file with error messages
*
* Parse an RNG schemas and then apply it to the related . xml
*
* Returns 0 in case of success , an error code otherwise
*/
static int
rngTest ( const char * filename ,
const char * resul ATTRIBUTE_UNUSED ,
const char * errr ATTRIBUTE_UNUSED ,
int options ) {
const char * base = baseFilename ( filename ) ;
const char * base2 ;
const char * instance ;
xmlRelaxNGParserCtxtPtr ctxt ;
xmlRelaxNGPtr schemas ;
2010-01-22 16:24:25 +03:00
int res = 0 , len , ret = 0 ;
2022-04-04 04:12:49 +03:00
int parseErrorsSize ;
2005-07-07 00:41:33 +04:00
char pattern [ 500 ] ;
char prefix [ 500 ] ;
char result [ 500 ] ;
char err [ 500 ] ;
glob_t globbuf ;
size_t i ;
char count = 0 ;
/* first compile the schemas if possible */
ctxt = xmlRelaxNGNewParserCtxt ( filename ) ;
2023-12-18 23:41:30 +03:00
xmlRelaxNGSetParserStructuredErrors ( ctxt , testStructuredErrorHandler ,
NULL ) ;
2005-07-07 00:41:33 +04:00
schemas = xmlRelaxNGParse ( ctxt ) ;
xmlRelaxNGFreeParserCtxt ( ctxt ) ;
2022-04-04 04:12:49 +03:00
if ( schemas = = NULL )
testErrorHandler ( NULL , " Relax-NG schema %s failed to compile \n " ,
filename ) ;
parseErrorsSize = testErrorsSize ;
2005-07-07 00:41:33 +04:00
/*
* most of the mess is about the output filenames generated by the Makefile
*/
len = strlen ( base ) ;
if ( ( len > 499 ) | | ( len < 5 ) ) {
xmlRelaxNGFree ( schemas ) ;
return ( - 1 ) ;
}
len - = 4 ; /* remove trailing .rng */
memcpy ( prefix , base , len ) ;
prefix [ len ] = 0 ;
2019-01-01 18:30:38 +03:00
if ( snprintf ( pattern , 499 , " ./test/relaxng/%s_?.xml " , prefix ) > = 499 )
pattern [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
globbuf . gl_offs = 0 ;
glob ( pattern , GLOB_DOOFFS , NULL , & globbuf ) ;
for ( i = 0 ; i < globbuf . gl_pathc ; i + + ) {
2022-04-04 04:12:49 +03:00
testErrorsSize = parseErrorsSize ;
testErrors [ parseErrorsSize ] = 0 ;
2005-07-07 00:41:33 +04:00
instance = globbuf . gl_pathv [ i ] ;
base2 = baseFilename ( instance ) ;
len = strlen ( base2 ) ;
if ( ( len > 6 ) & & ( base2 [ len - 6 ] = = ' _ ' ) ) {
count = base2 [ len - 5 ] ;
2019-01-01 18:30:38 +03:00
res = snprintf ( result , 499 , " result/relaxng/%s_%c " ,
2005-07-07 00:41:33 +04:00
prefix , count ) ;
2019-01-01 18:30:38 +03:00
if ( res > = 499 )
result [ 499 ] = 0 ;
res = snprintf ( err , 499 , " result/relaxng/%s_%c.err " ,
2005-07-07 00:41:33 +04:00
prefix , count ) ;
2019-01-01 18:30:38 +03:00
if ( res > = 499 )
err [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
} else {
fprintf ( stderr , " don't know how to process %s \n " , instance ) ;
continue ;
}
2022-04-04 04:12:49 +03:00
if ( schemas ! = NULL ) {
2005-07-07 00:41:33 +04:00
nb_tests + + ;
2022-04-04 04:12:49 +03:00
res = rngOneTest ( filename , instance , result , options , schemas ) ;
2005-07-07 00:41:33 +04:00
if ( res ! = 0 )
ret = res ;
}
2022-04-04 04:12:49 +03:00
if ( compareFileMem ( err , testErrors , testErrorsSize ) ) {
fprintf ( stderr , " Error for %s on %s failed \n " , instance ,
filename ) ;
2023-12-21 17:34:24 +03:00
ret = 1 ;
2022-04-04 04:12:49 +03:00
}
2005-07-07 00:41:33 +04:00
}
globfree ( & globbuf ) ;
xmlRelaxNGFree ( schemas ) ;
2009-09-07 16:58:47 +04:00
return ( ret ) ;
2005-07-07 00:41:33 +04:00
}
# ifdef LIBXML_READER_ENABLED
/**
* rngStreamTest :
* @ filename : the schemas file
* @ result : the file with expected result
* @ err : the file with error messages
*
2008-08-25 18:53:31 +04:00
* Parse a set of files with streaming , applying an RNG schemas
2005-07-07 00:41:33 +04:00
*
* Returns 0 in case of success , an error code otherwise
*/
static int
rngStreamTest ( const char * filename ,
const char * resul ATTRIBUTE_UNUSED ,
const char * errr ATTRIBUTE_UNUSED ,
int options ) {
const char * base = baseFilename ( filename ) ;
const char * base2 ;
const char * instance ;
int res = 0 , len , ret ;
char pattern [ 500 ] ;
char prefix [ 500 ] ;
char result [ 500 ] ;
char err [ 500 ] ;
glob_t globbuf ;
size_t i ;
char count = 0 ;
xmlTextReaderPtr reader ;
int disable_err = 0 ;
/*
* most of the mess is about the output filenames generated by the Makefile
*/
len = strlen ( base ) ;
if ( ( len > 499 ) | | ( len < 5 ) ) {
fprintf ( stderr , " len(base) == %d ! \n " , len ) ;
return ( - 1 ) ;
}
len - = 4 ; /* remove trailing .rng */
memcpy ( prefix , base , len ) ;
prefix [ len ] = 0 ;
/*
* strictly unifying the error messages is nearly impossible this
* hack is also done in the Makefile
*/
if ( ( ! strcmp ( prefix , " tutor10_1 " ) ) | | ( ! strcmp ( prefix , " tutor10_2 " ) ) | |
2009-08-26 20:37:43 +04:00
( ! strcmp ( prefix , " tutor3_2 " ) ) | | ( ! strcmp ( prefix , " 307377 " ) ) | |
( ! strcmp ( prefix , " tutor8_2 " ) ) )
2005-07-07 00:41:33 +04:00
disable_err = 1 ;
2019-01-01 18:30:38 +03:00
if ( snprintf ( pattern , 499 , " ./test/relaxng/%s_?.xml " , prefix ) > = 499 )
pattern [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
globbuf . gl_offs = 0 ;
glob ( pattern , GLOB_DOOFFS , NULL , & globbuf ) ;
for ( i = 0 ; i < globbuf . gl_pathc ; i + + ) {
testErrorsSize = 0 ;
testErrors [ 0 ] = 0 ;
instance = globbuf . gl_pathv [ i ] ;
base2 = baseFilename ( instance ) ;
len = strlen ( base2 ) ;
if ( ( len > 6 ) & & ( base2 [ len - 6 ] = = ' _ ' ) ) {
count = base2 [ len - 5 ] ;
2019-01-01 18:30:38 +03:00
ret = snprintf ( result , 499 , " result/relaxng/%s_%c " ,
2005-07-07 00:41:33 +04:00
prefix , count ) ;
2019-01-01 18:30:38 +03:00
if ( ret > = 499 )
result [ 499 ] = 0 ;
ret = snprintf ( err , 499 , " result/relaxng/%s_%c.err " ,
2005-07-07 00:41:33 +04:00
prefix , count ) ;
2019-01-01 18:30:38 +03:00
if ( ret > = 499 )
err [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
} else {
fprintf ( stderr , " don't know how to process %s \n " , instance ) ;
continue ;
}
reader = xmlReaderForFile ( instance , NULL , options ) ;
2023-12-18 23:41:30 +03:00
xmlTextReaderSetStructuredErrorHandler ( reader ,
testStructuredErrorHandler , NULL ) ;
2005-07-07 00:41:33 +04:00
if ( reader = = NULL ) {
2019-09-30 18:04:54 +03:00
fprintf ( stderr , " Failed to build reader for %s \n " , instance ) ;
2005-07-07 00:41:33 +04:00
}
if ( disable_err = = 1 )
2012-10-25 11:39:39 +04:00
ret = streamProcessTest ( instance , result , NULL , reader , filename ,
options ) ;
2005-07-07 00:41:33 +04:00
else
2012-10-25 11:39:39 +04:00
ret = streamProcessTest ( instance , result , err , reader , filename ,
options ) ;
2005-07-07 00:41:33 +04:00
xmlFreeTextReader ( reader ) ;
if ( ret ! = 0 ) {
fprintf ( stderr , " instance %s failed \n " , instance ) ;
res = ret ;
}
}
globfree ( & globbuf ) ;
return ( res ) ;
}
# endif /* READER */
# endif
# ifdef LIBXML_PATTERN_ENABLED
# ifdef LIBXML_READER_ENABLED
/************************************************************************
* *
* Patterns tests *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void patternNode ( FILE * out , xmlTextReaderPtr reader ,
const char * pattern , xmlPatternPtr patternc ,
xmlStreamCtxtPtr patstream ) {
xmlChar * path = NULL ;
int match = - 1 ;
int type , empty ;
type = xmlTextReaderNodeType ( reader ) ;
empty = xmlTextReaderIsEmptyElement ( reader ) ;
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
if ( type = = XML_READER_TYPE_ELEMENT ) {
/* do the check only on element start */
match = xmlPatternMatch ( patternc , xmlTextReaderCurrentNode ( reader ) ) ;
if ( match ) {
path = xmlGetNodePath ( xmlTextReaderCurrentNode ( reader ) ) ;
fprintf ( out , " Node %s matches pattern %s \n " , path , pattern ) ;
}
}
if ( patstream ! = NULL ) {
int ret ;
if ( type = = XML_READER_TYPE_ELEMENT ) {
ret = xmlStreamPush ( patstream ,
xmlTextReaderConstLocalName ( reader ) ,
xmlTextReaderConstNamespaceUri ( reader ) ) ;
if ( ret < 0 ) {
fprintf ( out , " xmlStreamPush() failure \n " ) ;
xmlFreeStreamCtxt ( patstream ) ;
patstream = NULL ;
} else if ( ret ! = match ) {
if ( path = = NULL ) {
path = xmlGetNodePath (
xmlTextReaderCurrentNode ( reader ) ) ;
}
fprintf ( out ,
" xmlPatternMatch and xmlStreamPush disagree \n " ) ;
fprintf ( out ,
" pattern %s node %s \n " ,
pattern , path ) ;
}
2008-08-25 18:53:31 +04:00
}
2005-07-07 00:41:33 +04:00
if ( ( type = = XML_READER_TYPE_END_ELEMENT ) | |
( ( type = = XML_READER_TYPE_ELEMENT ) & & ( empty ) ) ) {
ret = xmlStreamPop ( patstream ) ;
if ( ret < 0 ) {
fprintf ( out , " xmlStreamPop() failure \n " ) ;
xmlFreeStreamCtxt ( patstream ) ;
patstream = NULL ;
}
}
}
if ( path ! = NULL )
xmlFree ( path ) ;
}
/**
* patternTest :
* @ filename : the schemas file
* @ result : the file with expected result
* @ err : the file with error messages
*
2008-08-25 18:53:31 +04:00
* Parse a set of files with streaming , applying an RNG schemas
2005-07-07 00:41:33 +04:00
*
* Returns 0 in case of success , an error code otherwise
*/
static int
patternTest ( const char * filename ,
const char * resul ATTRIBUTE_UNUSED ,
const char * err ATTRIBUTE_UNUSED ,
int options ) {
xmlPatternPtr patternc = NULL ;
xmlStreamCtxtPtr patstream = NULL ;
FILE * o , * f ;
char str [ 1024 ] ;
char xml [ 500 ] ;
char result [ 500 ] ;
int len , i ;
int ret = 0 , res ;
char * temp ;
xmlTextReaderPtr reader ;
xmlDocPtr doc ;
len = strlen ( filename ) ;
len - = 4 ;
memcpy ( xml , filename , len ) ;
xml [ len ] = 0 ;
2019-01-01 18:30:38 +03:00
if ( snprintf ( result , 499 , " result/pattern/%s " , baseFilename ( xml ) ) > = 499 )
result [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
memcpy ( xml + len , " .xml " , 5 ) ;
2016-05-22 04:58:30 +03:00
if ( ! checkTestFile ( xml ) & & ! update_results ) {
2005-07-07 00:41:33 +04:00
fprintf ( stderr , " Missing xml file %s \n " , xml ) ;
return ( - 1 ) ;
}
f = fopen ( filename , " rb " ) ;
if ( f = = NULL ) {
fprintf ( stderr , " Failed to open %s \n " , filename ) ;
return ( - 1 ) ;
}
2020-06-04 12:58:04 +03:00
temp = resultFilename ( filename , temp_directory , " .res " ) ;
2005-07-07 00:41:33 +04:00
if ( temp = = NULL ) {
fprintf ( stderr , " Out of memory \n " ) ;
fatalError ( ) ;
}
o = fopen ( temp , " wb " ) ;
if ( o = = NULL ) {
fprintf ( stderr , " failed to open output file %s \n " , temp ) ;
fclose ( f ) ;
free ( temp ) ;
return ( - 1 ) ;
}
while ( 1 ) {
/*
* read one line in string buffer .
*/
if ( fgets ( & str [ 0 ] , sizeof ( str ) - 1 , f ) = = NULL )
break ;
/*
* remove the ending spaces
*/
i = strlen ( str ) ;
while ( ( i > 0 ) & &
( ( str [ i - 1 ] = = ' \n ' ) | | ( str [ i - 1 ] = = ' \r ' ) | |
( str [ i - 1 ] = = ' ' ) | | ( str [ i - 1 ] = = ' \t ' ) ) ) {
i - - ;
str [ i ] = 0 ;
}
doc = xmlReadFile ( xml , NULL , options ) ;
if ( doc = = NULL ) {
fprintf ( stderr , " Failed to parse %s \n " , xml ) ;
ret = 1 ;
} else {
xmlNodePtr root ;
const xmlChar * namespaces [ 22 ] ;
int j ;
xmlNsPtr ns ;
root = xmlDocGetRootElement ( doc ) ;
for ( ns = root - > nsDef , j = 0 ; ns ! = NULL & & j < 20 ; ns = ns - > next ) {
namespaces [ j + + ] = ns - > href ;
namespaces [ j + + ] = ns - > prefix ;
}
namespaces [ j + + ] = NULL ;
2009-09-05 16:52:55 +04:00
namespaces [ j ] = NULL ;
2005-07-07 00:41:33 +04:00
patternc = xmlPatterncompile ( ( const xmlChar * ) str , doc - > dict ,
0 , & namespaces [ 0 ] ) ;
if ( patternc = = NULL ) {
testErrorHandler ( NULL ,
" Pattern %s failed to compile \n " , str ) ;
xmlFreeDoc ( doc ) ;
ret = 1 ;
continue ;
}
patstream = xmlPatternGetStreamCtxt ( patternc ) ;
if ( patstream ! = NULL ) {
ret = xmlStreamPush ( patstream , NULL , NULL ) ;
if ( ret < 0 ) {
fprintf ( stderr , " xmlStreamPush() failure \n " ) ;
xmlFreeStreamCtxt ( patstream ) ;
patstream = NULL ;
}
}
nb_tests + + ;
reader = xmlReaderWalker ( doc ) ;
res = xmlTextReaderRead ( reader ) ;
while ( res = = 1 ) {
patternNode ( o , reader , str , patternc , patstream ) ;
res = xmlTextReaderRead ( reader ) ;
}
if ( res ! = 0 ) {
fprintf ( o , " %s : failed to parse \n " , filename ) ;
}
xmlFreeTextReader ( reader ) ;
xmlFreeDoc ( doc ) ;
xmlFreeStreamCtxt ( patstream ) ;
patstream = NULL ;
xmlFreePattern ( patternc ) ;
}
}
fclose ( f ) ;
fclose ( o ) ;
ret = compareFiles ( temp , result ) ;
if ( ret ) {
2016-05-22 06:14:45 +03:00
fprintf ( stderr , " Result for %s failed in %s \n " , filename , result ) ;
2005-07-07 00:41:33 +04:00
ret = 1 ;
}
2009-09-05 16:52:55 +04:00
if ( temp ! = NULL ) {
unlink ( temp ) ;
free ( temp ) ;
}
2005-07-07 00:41:33 +04:00
return ( ret ) ;
}
# endif /* READER */
# endif /* PATTERN */
# ifdef LIBXML_C14N_ENABLED
/************************************************************************
* *
* Canonicalization tests *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static xmlXPathObjectPtr
load_xpath_expr ( xmlDocPtr parent_doc , const char * filename ) {
2008-08-25 18:53:31 +04:00
xmlXPathObjectPtr xpath ;
2005-07-07 00:41:33 +04:00
xmlDocPtr doc ;
xmlChar * expr ;
2008-08-25 18:53:31 +04:00
xmlXPathContextPtr ctx ;
2005-07-07 00:41:33 +04:00
xmlNodePtr node ;
xmlNsPtr ns ;
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
/*
* load XPath expr as a file
*/
2005-08-24 02:14:02 +04:00
doc = xmlReadFile ( filename , NULL , XML_PARSE_DTDATTR | XML_PARSE_NOENT ) ;
2005-07-07 00:41:33 +04:00
if ( doc = = NULL ) {
fprintf ( stderr , " Error: unable to parse file \" %s \" \n " , filename ) ;
return ( NULL ) ;
}
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
/*
* Check the document is of the right kind
2008-08-25 18:53:31 +04:00
*/
2005-07-07 00:41:33 +04:00
if ( xmlDocGetRootElement ( doc ) = = NULL ) {
fprintf ( stderr , " Error: empty document for file \" %s \" \n " , filename ) ;
xmlFreeDoc ( doc ) ;
return ( NULL ) ;
}
node = doc - > children ;
while ( node ! = NULL & & ! xmlStrEqual ( node - > name , ( const xmlChar * ) " XPath " ) ) {
node = node - > next ;
}
2008-08-25 18:53:31 +04:00
if ( node = = NULL ) {
2005-07-07 00:41:33 +04:00
fprintf ( stderr , " Error: XPath element expected in the file \" %s \" \n " , filename ) ;
xmlFreeDoc ( doc ) ;
return ( NULL ) ;
}
expr = xmlNodeGetContent ( node ) ;
if ( expr = = NULL ) {
fprintf ( stderr , " Error: XPath content element is NULL \" %s \" \n " , filename ) ;
xmlFreeDoc ( doc ) ;
return ( NULL ) ;
}
ctx = xmlXPathNewContext ( parent_doc ) ;
if ( ctx = = NULL ) {
fprintf ( stderr , " Error: unable to create new context \n " ) ;
2008-08-25 18:53:31 +04:00
xmlFree ( expr ) ;
xmlFreeDoc ( doc ) ;
2005-07-07 00:41:33 +04:00
return ( NULL ) ;
}
/*
* Register namespaces
*/
ns = node - > nsDef ;
while ( ns ! = NULL ) {
if ( xmlXPathRegisterNs ( ctx , ns - > prefix , ns - > href ) ! = 0 ) {
fprintf ( stderr , " Error: unable to register NS with prefix= \" %s \" and href= \" %s \" \n " , ns - > prefix , ns - > href ) ;
2008-08-25 18:53:31 +04:00
xmlFree ( expr ) ;
xmlXPathFreeContext ( ctx ) ;
xmlFreeDoc ( doc ) ;
2005-07-07 00:41:33 +04:00
return ( NULL ) ;
}
ns = ns - > next ;
}
2008-08-25 18:53:31 +04:00
/*
2005-07-07 00:41:33 +04:00
* Evaluate xpath
*/
xpath = xmlXPathEvalExpression ( expr , ctx ) ;
if ( xpath = = NULL ) {
fprintf ( stderr , " Error: unable to evaluate xpath expression \n " ) ;
2008-08-25 18:53:31 +04:00
xmlFree ( expr ) ;
xmlXPathFreeContext ( ctx ) ;
xmlFreeDoc ( doc ) ;
2005-07-07 00:41:33 +04:00
return ( NULL ) ;
}
/* print_xpath_nodes(xpath->nodesetval); */
2008-08-25 18:53:31 +04:00
xmlFree ( expr ) ;
xmlXPathFreeContext ( ctx ) ;
xmlFreeDoc ( doc ) ;
2005-07-07 00:41:33 +04:00
return ( xpath ) ;
}
/*
* Macro used to grow the current buffer .
*/
# define xxx_growBufferReentrant() { \
buffer_size * = 2 ; \
buffer = ( xmlChar * * ) \
2008-08-25 18:53:31 +04:00
xmlRealloc ( buffer , buffer_size * sizeof ( xmlChar * ) ) ; \
2005-07-07 00:41:33 +04:00
if ( buffer = = NULL ) { \
perror ( " realloc failed " ) ; \
return ( NULL ) ; \
} \
}
static xmlChar * *
parse_list ( xmlChar * str ) {
xmlChar * * buffer ;
xmlChar * * out = NULL ;
int buffer_size = 0 ;
int len ;
if ( str = = NULL ) {
return ( NULL ) ;
}
len = xmlStrlen ( str ) ;
if ( ( str [ 0 ] = = ' \' ' ) & & ( str [ len - 1 ] = = ' \' ' ) ) {
str [ len - 1 ] = ' \0 ' ;
str + + ;
}
/*
* allocate an translation buffer .
*/
buffer_size = 1000 ;
buffer = ( xmlChar * * ) xmlMalloc ( buffer_size * sizeof ( xmlChar * ) ) ;
if ( buffer = = NULL ) {
perror ( " malloc failed " ) ;
return ( NULL ) ;
}
out = buffer ;
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
while ( * str ! = ' \0 ' ) {
if ( out - buffer > buffer_size - 10 ) {
int indx = out - buffer ;
xxx_growBufferReentrant ( ) ;
out = & buffer [ indx ] ;
}
( * out + + ) = str ;
while ( * str ! = ' , ' & & * str ! = ' \0 ' ) + + str ;
if ( * str = = ' , ' ) * ( str + + ) = ' \0 ' ;
}
( * out ) = NULL ;
return buffer ;
}
2008-08-25 18:53:31 +04:00
static int
2009-07-09 12:26:22 +04:00
c14nRunTest ( const char * xml_filename , int with_comments , int mode ,
2005-07-07 00:41:33 +04:00
const char * xpath_filename , const char * ns_filename ,
const char * result_file ) {
xmlDocPtr doc ;
2008-08-25 18:53:31 +04:00
xmlXPathObjectPtr xpath = NULL ;
2005-07-07 00:41:33 +04:00
xmlChar * result = NULL ;
int ret ;
xmlChar * * inclusive_namespaces = NULL ;
const char * nslist = NULL ;
int nssize ;
/*
* build an XML tree from a the file ; we need to add default
* attributes and resolve all character and entities references
*/
2023-12-18 23:41:30 +03:00
doc = xmlReadFile ( xml_filename , NULL ,
XML_PARSE_DTDATTR | XML_PARSE_NOENT | XML_PARSE_NOWARNING ) ;
2005-07-07 00:41:33 +04:00
if ( doc = = NULL ) {
fprintf ( stderr , " Error: unable to parse file \" %s \" \n " , xml_filename ) ;
return ( - 1 ) ;
}
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
/*
* Check the document is of the right kind
2008-08-25 18:53:31 +04:00
*/
2005-07-07 00:41:33 +04:00
if ( xmlDocGetRootElement ( doc ) = = NULL ) {
fprintf ( stderr , " Error: empty document for file \" %s \" \n " , xml_filename ) ;
xmlFreeDoc ( doc ) ;
return ( - 1 ) ;
}
2008-08-25 18:53:31 +04:00
/*
* load xpath file if specified
2005-07-07 00:41:33 +04:00
*/
if ( xpath_filename ) {
xpath = load_xpath_expr ( doc , xpath_filename ) ;
if ( xpath = = NULL ) {
fprintf ( stderr , " Error: unable to evaluate xpath expression \n " ) ;
2008-08-25 18:53:31 +04:00
xmlFreeDoc ( doc ) ;
2005-07-07 00:41:33 +04:00
return ( - 1 ) ;
}
}
if ( ns_filename ! = NULL ) {
if ( loadMem ( ns_filename , & nslist , & nssize ) ) {
fprintf ( stderr , " Error: unable to evaluate xpath expression \n " ) ;
if ( xpath ! = NULL ) xmlXPathFreeObject ( xpath ) ;
2008-08-25 18:53:31 +04:00
xmlFreeDoc ( doc ) ;
2005-07-07 00:41:33 +04:00
return ( - 1 ) ;
}
inclusive_namespaces = parse_list ( ( xmlChar * ) nslist ) ;
}
/*
* Canonical form
2008-08-25 18:53:31 +04:00
*/
2005-07-07 00:41:33 +04:00
/* fprintf(stderr,"File \"%s\" loaded: start canonization\n", xml_filename); */
2008-08-25 18:53:31 +04:00
ret = xmlC14NDocDumpMemory ( doc ,
( xpath ) ? xpath - > nodesetval : NULL ,
2009-07-09 12:26:22 +04:00
mode , inclusive_namespaces ,
2005-07-07 00:41:33 +04:00
with_comments , & result ) ;
if ( ret > = 0 ) {
if ( result ! = NULL ) {
if ( compareFileMem ( result_file , ( const char * ) result , ret ) ) {
fprintf ( stderr , " Result mismatch for %s \n " , xml_filename ) ;
2009-07-09 12:26:22 +04:00
fprintf ( stderr , " RESULT: \n %s \n " , ( const char * ) result ) ;
2005-07-07 00:41:33 +04:00
ret = - 1 ;
}
}
} else {
fprintf ( stderr , " Error: failed to canonicalize XML file \" %s \" (ret=%d) \n " , xml_filename , ret ) ;
ret = - 1 ;
}
2008-08-25 18:53:31 +04:00
2005-07-07 00:41:33 +04:00
/*
* Cleanup
2008-08-25 18:53:31 +04:00
*/
2005-07-07 00:41:33 +04:00
if ( result ! = NULL ) xmlFree ( result ) ;
if ( xpath ! = NULL ) xmlXPathFreeObject ( xpath ) ;
if ( inclusive_namespaces ! = NULL ) xmlFree ( inclusive_namespaces ) ;
if ( nslist ! = NULL ) free ( ( char * ) nslist ) ;
2008-08-25 18:53:31 +04:00
xmlFreeDoc ( doc ) ;
2005-07-07 00:41:33 +04:00
return ( ret ) ;
}
static int
2009-07-09 12:26:22 +04:00
c14nCommonTest ( const char * filename , int with_comments , int mode ,
2005-07-07 00:41:33 +04:00
const char * subdir ) {
char buf [ 500 ] ;
char prefix [ 500 ] ;
const char * base ;
int len ;
char * result = NULL ;
char * xpath = NULL ;
char * ns = NULL ;
int ret = 0 ;
base = baseFilename ( filename ) ;
len = strlen ( base ) ;
len - = 4 ;
memcpy ( prefix , base , len ) ;
prefix [ len ] = 0 ;
2019-01-01 18:30:38 +03:00
if ( snprintf ( buf , 499 , " result/c14n/%s/%s " , subdir , prefix ) > = 499 )
buf [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
result = strdup ( buf ) ;
2019-01-01 18:30:38 +03:00
if ( snprintf ( buf , 499 , " test/c14n/%s/%s.xpath " , subdir , prefix ) > = 499 )
buf [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
if ( checkTestFile ( buf ) ) {
xpath = strdup ( buf ) ;
}
2019-01-01 18:30:38 +03:00
if ( snprintf ( buf , 499 , " test/c14n/%s/%s.ns " , subdir , prefix ) > = 499 )
buf [ 499 ] = 0 ;
2005-07-07 00:41:33 +04:00
if ( checkTestFile ( buf ) ) {
ns = strdup ( buf ) ;
}
nb_tests + + ;
2009-07-09 12:26:22 +04:00
if ( c14nRunTest ( filename , with_comments , mode ,
2005-07-07 00:41:33 +04:00
xpath , ns , result ) < 0 )
ret = 1 ;
if ( result ! = NULL ) free ( result ) ;
if ( xpath ! = NULL ) free ( xpath ) ;
if ( ns ! = NULL ) free ( ns ) ;
return ( ret ) ;
}
static int
c14nWithCommentTest ( const char * filename ,
const char * resul ATTRIBUTE_UNUSED ,
const char * err ATTRIBUTE_UNUSED ,
int options ATTRIBUTE_UNUSED ) {
2009-07-09 12:26:22 +04:00
return ( c14nCommonTest ( filename , 1 , XML_C14N_1_0 , " with-comments " ) ) ;
2005-07-07 00:41:33 +04:00
}
static int
c14nWithoutCommentTest ( const char * filename ,
const char * resul ATTRIBUTE_UNUSED ,
const char * err ATTRIBUTE_UNUSED ,
int options ATTRIBUTE_UNUSED ) {
2009-07-09 12:26:22 +04:00
return ( c14nCommonTest ( filename , 0 , XML_C14N_1_0 , " without-comments " ) ) ;
2005-07-07 00:41:33 +04:00
}
static int
c14nExcWithoutCommentTest ( const char * filename ,
const char * resul ATTRIBUTE_UNUSED ,
const char * err ATTRIBUTE_UNUSED ,
int options ATTRIBUTE_UNUSED ) {
2009-07-09 12:26:22 +04:00
return ( c14nCommonTest ( filename , 0 , XML_C14N_EXCLUSIVE_1_0 , " exc-without-comments " ) ) ;
}
static int
c14n11WithoutCommentTest ( const char * filename ,
const char * resul ATTRIBUTE_UNUSED ,
const char * err ATTRIBUTE_UNUSED ,
int options ATTRIBUTE_UNUSED ) {
return ( c14nCommonTest ( filename , 0 , XML_C14N_1_1 , " 1-1-without-comments " ) ) ;
2005-07-07 00:41:33 +04:00
}
# endif
2017-06-16 22:27:47 +03:00
# if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
2005-07-07 00:41:33 +04:00
/************************************************************************
* *
* Catalog and threads test *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define MAX_ARGC 20
2017-10-21 15:43:00 +03:00
typedef struct {
const char * filename ;
int okay ;
} xmlThreadParams ;
2005-07-07 00:41:33 +04:00
static const char * catalog = " test/threads/complex.xml " ;
2017-10-21 15:43:00 +03:00
static xmlThreadParams threadParams [ ] = {
{ " test/threads/abc.xml " , 0 } ,
{ " test/threads/acb.xml " , 0 } ,
{ " test/threads/bac.xml " , 0 } ,
{ " test/threads/bca.xml " , 0 } ,
{ " test/threads/cab.xml " , 0 } ,
{ " test/threads/cba.xml " , 0 } ,
{ " test/threads/invalid.xml " , 0 }
2005-07-07 00:41:33 +04:00
} ;
2017-10-21 15:43:00 +03:00
static const unsigned int num_threads = sizeof ( threadParams ) /
sizeof ( threadParams [ 0 ] ) ;
2005-07-07 00:41:33 +04:00
static void *
thread_specific_data ( void * private_data )
{
xmlDocPtr myDoc ;
2017-10-21 15:43:00 +03:00
xmlThreadParams * params = ( xmlThreadParams * ) private_data ;
const char * filename = params - > filename ;
2005-07-07 00:41:33 +04:00
int okay = 1 ;
2024-06-16 17:30:54 +03:00
if ( xmlCheckThreadLocalStorage ( ) ! = 0 ) {
printf ( " xmlCheckThreadLocalStorage failed \n " ) ;
params - > okay = 0 ;
return ( NULL ) ;
}
2023-10-18 21:06:35 +03:00
# ifdef LIBXML_THREAD_ALLOC_ENABLED
xmlMemSetup ( xmlMemFree , xmlMemMalloc , xmlMemRealloc , xmlMemoryStrdup ) ;
# endif
2023-09-20 16:49:03 +03:00
myDoc = xmlReadFile ( filename , NULL , XML_PARSE_NOENT | XML_PARSE_DTDLOAD ) ;
2005-07-07 00:41:33 +04:00
if ( myDoc ) {
xmlFreeDoc ( myDoc ) ;
} else {
printf ( " parse failed \n " ) ;
okay = 0 ;
}
2017-10-21 15:43:00 +03:00
params - > okay = okay ;
return ( NULL ) ;
2005-07-07 00:41:33 +04:00
}
2022-03-01 00:42:10 +03:00
# if defined(_WIN32)
2005-07-07 00:41:33 +04:00
# include <windows.h>
# include <string.h>
# define TEST_REPEAT_COUNT 500
static HANDLE tid [ MAX_ARGC ] ;
static DWORD WINAPI
win32_thread_specific_data ( void * private_data )
{
2017-10-21 15:43:00 +03:00
thread_specific_data ( private_data ) ;
return ( 0 ) ;
2005-07-07 00:41:33 +04:00
}
static int
testThread ( void )
{
unsigned int i , repeat ;
BOOL ret ;
int res = 0 ;
xmlInitParser ( ) ;
for ( repeat = 0 ; repeat < TEST_REPEAT_COUNT ; repeat + + ) {
xmlLoadCatalog ( catalog ) ;
nb_tests + + ;
for ( i = 0 ; i < num_threads ; i + + ) {
tid [ i ] = ( HANDLE ) - 1 ;
}
for ( i = 0 ; i < num_threads ; i + + ) {
DWORD useless ;
tid [ i ] = CreateThread ( NULL , 0 ,
2008-08-25 18:53:31 +04:00
win32_thread_specific_data ,
2017-10-21 15:43:00 +03:00
( void * ) & threadParams [ i ] , 0 ,
2005-07-07 00:41:33 +04:00
& useless ) ;
if ( tid [ i ] = = NULL ) {
fprintf ( stderr , " CreateThread failed \n " ) ;
return ( 1 ) ;
}
}
if ( WaitForMultipleObjects ( num_threads , tid , TRUE , INFINITE ) = =
WAIT_FAILED ) {
fprintf ( stderr , " WaitForMultipleObjects failed \n " ) ;
return ( 1 ) ;
}
for ( i = 0 ; i < num_threads ; i + + ) {
2017-10-21 15:43:00 +03:00
DWORD exitCode ;
ret = GetExitCodeThread ( tid [ i ] , & exitCode ) ;
2005-07-07 00:41:33 +04:00
if ( ret = = 0 ) {
fprintf ( stderr , " GetExitCodeThread failed \n " ) ;
return ( 1 ) ;
}
CloseHandle ( tid [ i ] ) ;
}
xmlCatalogCleanup ( ) ;
for ( i = 0 ; i < num_threads ; i + + ) {
2017-10-21 15:43:00 +03:00
if ( threadParams [ i ] . okay = = 0 ) {
2005-07-07 00:41:33 +04:00
fprintf ( stderr , " Thread %d handling %s failed \n " ,
2017-10-21 15:43:00 +03:00
i , threadParams [ i ] . filename ) ;
2005-07-07 00:41:33 +04:00
res = 1 ;
}
}
}
return ( res ) ;
}
2012-08-07 06:14:56 +04:00
# elif defined HAVE_PTHREAD_H
# include <pthread.h>
static pthread_t tid [ MAX_ARGC ] ;
static int
testThread ( void )
{
unsigned int i , repeat ;
int ret ;
int res = 0 ;
xmlInitParser ( ) ;
for ( repeat = 0 ; repeat < 500 ; repeat + + ) {
xmlLoadCatalog ( catalog ) ;
nb_tests + + ;
for ( i = 0 ; i < num_threads ; i + + ) {
tid [ i ] = ( pthread_t ) - 1 ;
}
for ( i = 0 ; i < num_threads ; i + + ) {
ret = pthread_create ( & tid [ i ] , 0 , thread_specific_data ,
2017-10-21 15:43:00 +03:00
( void * ) & threadParams [ i ] ) ;
2012-08-07 06:14:56 +04:00
if ( ret ! = 0 ) {
fprintf ( stderr , " pthread_create failed \n " ) ;
return ( 1 ) ;
}
}
for ( i = 0 ; i < num_threads ; i + + ) {
2017-10-21 15:43:00 +03:00
void * result ;
ret = pthread_join ( tid [ i ] , & result ) ;
2012-08-07 06:14:56 +04:00
if ( ret ! = 0 ) {
fprintf ( stderr , " pthread_join failed \n " ) ;
return ( 1 ) ;
}
}
xmlCatalogCleanup ( ) ;
for ( i = 0 ; i < num_threads ; i + + )
2017-10-21 15:43:00 +03:00
if ( threadParams [ i ] . okay = = 0 ) {
2012-08-07 06:14:56 +04:00
fprintf ( stderr , " Thread %d handling %s failed \n " ,
2017-10-21 15:43:00 +03:00
i , threadParams [ i ] . filename ) ;
2012-08-07 06:14:56 +04:00
res = 1 ;
}
}
return ( res ) ;
}
2005-07-07 00:41:33 +04:00
# else
static int
testThread ( void )
{
fprintf ( stderr ,
" Specific platform thread support not detected \n " ) ;
return ( - 1 ) ;
}
# endif
2008-08-25 18:53:31 +04:00
static int
2005-07-07 00:41:33 +04:00
threadsTest ( const char * filename ATTRIBUTE_UNUSED ,
const char * resul ATTRIBUTE_UNUSED ,
const char * err ATTRIBUTE_UNUSED ,
int options ATTRIBUTE_UNUSED ) {
2024-06-15 20:37:27 +03:00
return ( testThread ( ) ) ;
2005-07-07 00:41:33 +04:00
}
# endif
2020-07-09 04:21:07 +03:00
# if defined(LIBXML_REGEXP_ENABLED)
/************************************************************************
* *
* Regexp tests *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void testRegexp ( FILE * output , xmlRegexpPtr comp , const char * value ) {
int ret ;
ret = xmlRegexpExec ( comp , ( const xmlChar * ) value ) ;
if ( ret = = 1 )
fprintf ( output , " %s: Ok \n " , value ) ;
else if ( ret = = 0 )
fprintf ( output , " %s: Fail \n " , value ) ;
else
fprintf ( output , " %s: Error: %d \n " , value , ret ) ;
}
static int
regexpTest ( const char * filename , const char * result , const char * err ,
int options ATTRIBUTE_UNUSED ) {
xmlRegexpPtr comp = NULL ;
FILE * input , * output ;
char * temp ;
char expression [ 5000 ] ;
int len , ret , res = 0 ;
2024-01-04 15:59:23 +03:00
/*
* TODO : Custom error handler for regexp
*/
2023-12-18 23:41:30 +03:00
xmlSetStructuredErrorFunc ( NULL , testStructuredErrorHandler ) ;
2022-09-02 18:26:47 +03:00
nb_tests + + ;
input = fopen ( filename , " rb " ) ;
2020-07-09 04:21:07 +03:00
if ( input = = NULL ) {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2020-07-09 04:21:07 +03:00
" Cannot open %s for reading \n " , filename ) ;
2023-12-18 23:41:30 +03:00
ret = - 1 ;
goto done ;
2020-07-09 04:21:07 +03:00
}
temp = resultFilename ( filename , " " , " .res " ) ;
if ( temp = = NULL ) {
fprintf ( stderr , " Out of memory \n " ) ;
fatalError ( ) ;
}
output = fopen ( temp , " wb " ) ;
if ( output = = NULL ) {
fprintf ( stderr , " failed to open output file %s \n " , temp ) ;
free ( temp ) ;
2023-12-18 23:41:30 +03:00
ret = - 1 ;
goto done ;
2020-07-09 04:21:07 +03:00
}
while ( fgets ( expression , 4500 , input ) ! = NULL ) {
len = strlen ( expression ) ;
len - - ;
while ( ( len > = 0 ) & &
( ( expression [ len ] = = ' \n ' ) | | ( expression [ len ] = = ' \t ' ) | |
( expression [ len ] = = ' \r ' ) | | ( expression [ len ] = = ' ' ) ) ) len - - ;
expression [ len + 1 ] = 0 ;
if ( len > = 0 ) {
if ( expression [ 0 ] = = ' # ' )
continue ;
if ( ( expression [ 0 ] = = ' = ' ) & & ( expression [ 1 ] = = ' > ' ) ) {
char * pattern = & expression [ 2 ] ;
if ( comp ! = NULL ) {
xmlRegFreeRegexp ( comp ) ;
comp = NULL ;
}
fprintf ( output , " Regexp: %s \n " , pattern ) ;
comp = xmlRegexpCompile ( ( const xmlChar * ) pattern ) ;
if ( comp = = NULL ) {
fprintf ( output , " failed to compile \n " ) ;
break ;
}
} else if ( comp = = NULL ) {
fprintf ( output , " Regexp: %s \n " , expression ) ;
comp = xmlRegexpCompile ( ( const xmlChar * ) expression ) ;
if ( comp = = NULL ) {
fprintf ( output , " failed to compile \n " ) ;
break ;
}
} else if ( comp ! = NULL ) {
testRegexp ( output , comp , expression ) ;
}
}
}
fclose ( output ) ;
fclose ( input ) ;
if ( comp ! = NULL )
xmlRegFreeRegexp ( comp ) ;
ret = compareFiles ( temp , result ) ;
if ( ret ) {
fprintf ( stderr , " Result for %s failed in %s \n " , filename , result ) ;
res = 1 ;
}
if ( temp ! = NULL ) {
unlink ( temp ) ;
free ( temp ) ;
}
ret = compareFileMem ( err , testErrors , testErrorsSize ) ;
if ( ret ! = 0 ) {
fprintf ( stderr , " Error for %s failed \n " , filename ) ;
res = 1 ;
}
2023-12-18 23:41:30 +03:00
done :
xmlSetStructuredErrorFunc ( NULL , NULL ) ;
2020-07-09 04:21:07 +03:00
return ( res ) ;
}
2022-09-02 18:26:47 +03:00
/************************************************************************
* *
* Automata tests *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int scanNumber ( char * * ptr ) {
int ret = 0 ;
char * cur ;
cur = * ptr ;
while ( ( * cur > = ' 0 ' ) & & ( * cur < = ' 9 ' ) ) {
ret = ret * 10 + ( * cur - ' 0 ' ) ;
cur + + ;
}
* ptr = cur ;
return ( ret ) ;
}
static int
automataTest ( const char * filename , const char * result ,
const char * err ATTRIBUTE_UNUSED , int options ATTRIBUTE_UNUSED ) {
FILE * input , * output ;
char * temp ;
char expr [ 5000 ] ;
int len ;
int ret ;
int i ;
int res = 0 ;
xmlAutomataPtr am ;
xmlAutomataStatePtr states [ 1000 ] ;
xmlRegexpPtr regexp = NULL ;
xmlRegExecCtxtPtr exec = NULL ;
nb_tests + + ;
for ( i = 0 ; i < 1000 ; i + + )
states [ i ] = NULL ;
input = fopen ( filename , " rb " ) ;
if ( input = = NULL ) {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2022-09-02 18:26:47 +03:00
" Cannot open %s for reading \n " , filename ) ;
return ( - 1 ) ;
}
temp = resultFilename ( filename , " " , " .res " ) ;
if ( temp = = NULL ) {
fprintf ( stderr , " Out of memory \n " ) ;
fatalError ( ) ;
}
output = fopen ( temp , " wb " ) ;
if ( output = = NULL ) {
fprintf ( stderr , " failed to open output file %s \n " , temp ) ;
free ( temp ) ;
return ( - 1 ) ;
}
am = xmlNewAutomata ( ) ;
if ( am = = NULL ) {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2022-09-02 18:26:47 +03:00
" Cannot create automata \n " ) ;
fclose ( input ) ;
return ( - 1 ) ;
}
states [ 0 ] = xmlAutomataGetInitState ( am ) ;
if ( states [ 0 ] = = NULL ) {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2022-09-02 18:26:47 +03:00
" Cannot get start state \n " ) ;
xmlFreeAutomata ( am ) ;
fclose ( input ) ;
return ( - 1 ) ;
}
ret = 0 ;
while ( fgets ( expr , 4500 , input ) ! = NULL ) {
if ( expr [ 0 ] = = ' # ' )
continue ;
len = strlen ( expr ) ;
len - - ;
while ( ( len > = 0 ) & &
( ( expr [ len ] = = ' \n ' ) | | ( expr [ len ] = = ' \t ' ) | |
( expr [ len ] = = ' \r ' ) | | ( expr [ len ] = = ' ' ) ) ) len - - ;
expr [ len + 1 ] = 0 ;
if ( len > = 0 ) {
if ( ( am ! = NULL ) & & ( expr [ 0 ] = = ' t ' ) & & ( expr [ 1 ] = = ' ' ) ) {
char * ptr = & expr [ 2 ] ;
int from , to ;
from = scanNumber ( & ptr ) ;
if ( * ptr ! = ' ' ) {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2022-09-02 18:26:47 +03:00
" Bad line %s \n " , expr ) ;
break ;
}
if ( states [ from ] = = NULL )
states [ from ] = xmlAutomataNewState ( am ) ;
ptr + + ;
to = scanNumber ( & ptr ) ;
if ( * ptr ! = ' ' ) {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2022-09-02 18:26:47 +03:00
" Bad line %s \n " , expr ) ;
break ;
}
if ( states [ to ] = = NULL )
states [ to ] = xmlAutomataNewState ( am ) ;
ptr + + ;
xmlAutomataNewTransition ( am , states [ from ] , states [ to ] ,
BAD_CAST ptr , NULL ) ;
} else if ( ( am ! = NULL ) & & ( expr [ 0 ] = = ' e ' ) & & ( expr [ 1 ] = = ' ' ) ) {
char * ptr = & expr [ 2 ] ;
int from , to ;
from = scanNumber ( & ptr ) ;
if ( * ptr ! = ' ' ) {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2022-09-02 18:26:47 +03:00
" Bad line %s \n " , expr ) ;
break ;
}
if ( states [ from ] = = NULL )
states [ from ] = xmlAutomataNewState ( am ) ;
ptr + + ;
to = scanNumber ( & ptr ) ;
if ( states [ to ] = = NULL )
states [ to ] = xmlAutomataNewState ( am ) ;
xmlAutomataNewEpsilon ( am , states [ from ] , states [ to ] ) ;
} else if ( ( am ! = NULL ) & & ( expr [ 0 ] = = ' f ' ) & & ( expr [ 1 ] = = ' ' ) ) {
char * ptr = & expr [ 2 ] ;
int state ;
state = scanNumber ( & ptr ) ;
if ( states [ state ] = = NULL ) {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2022-09-02 18:26:47 +03:00
" Bad state %d : %s \n " , state , expr ) ;
break ;
}
xmlAutomataSetFinalState ( am , states [ state ] ) ;
} else if ( ( am ! = NULL ) & & ( expr [ 0 ] = = ' c ' ) & & ( expr [ 1 ] = = ' ' ) ) {
char * ptr = & expr [ 2 ] ;
int from , to ;
int min , max ;
from = scanNumber ( & ptr ) ;
if ( * ptr ! = ' ' ) {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2022-09-02 18:26:47 +03:00
" Bad line %s \n " , expr ) ;
break ;
}
if ( states [ from ] = = NULL )
states [ from ] = xmlAutomataNewState ( am ) ;
ptr + + ;
to = scanNumber ( & ptr ) ;
if ( * ptr ! = ' ' ) {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2022-09-02 18:26:47 +03:00
" Bad line %s \n " , expr ) ;
break ;
}
if ( states [ to ] = = NULL )
states [ to ] = xmlAutomataNewState ( am ) ;
ptr + + ;
min = scanNumber ( & ptr ) ;
if ( * ptr ! = ' ' ) {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2022-09-02 18:26:47 +03:00
" Bad line %s \n " , expr ) ;
break ;
}
ptr + + ;
max = scanNumber ( & ptr ) ;
if ( * ptr ! = ' ' ) {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2022-09-02 18:26:47 +03:00
" Bad line %s \n " , expr ) ;
break ;
}
ptr + + ;
xmlAutomataNewCountTrans ( am , states [ from ] , states [ to ] ,
BAD_CAST ptr , min , max , NULL ) ;
} else if ( ( am ! = NULL ) & & ( expr [ 0 ] = = ' - ' ) & & ( expr [ 1 ] = = ' - ' ) ) {
/* end of the automata */
regexp = xmlAutomataCompile ( am ) ;
xmlFreeAutomata ( am ) ;
am = NULL ;
if ( regexp = = NULL ) {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2022-09-02 18:26:47 +03:00
" Failed to compile the automata " ) ;
break ;
}
} else if ( ( expr [ 0 ] = = ' = ' ) & & ( expr [ 1 ] = = ' > ' ) ) {
if ( regexp = = NULL ) {
fprintf ( output , " => failed not compiled \n " ) ;
} else {
if ( exec = = NULL )
exec = xmlRegNewExecCtxt ( regexp , NULL , NULL ) ;
if ( ret = = 0 ) {
ret = xmlRegExecPushString ( exec , NULL , NULL ) ;
}
if ( ret = = 1 )
fprintf ( output , " => Passed \n " ) ;
else if ( ( ret = = 0 ) | | ( ret = = - 1 ) )
fprintf ( output , " => Failed \n " ) ;
else if ( ret < 0 )
fprintf ( output , " => Error \n " ) ;
xmlRegFreeExecCtxt ( exec ) ;
exec = NULL ;
}
ret = 0 ;
} else if ( regexp ! = NULL ) {
if ( exec = = NULL )
exec = xmlRegNewExecCtxt ( regexp , NULL , NULL ) ;
ret = xmlRegExecPushString ( exec , BAD_CAST expr , NULL ) ;
} else {
2023-12-18 23:41:30 +03:00
fprintf ( stderr ,
2022-09-02 18:26:47 +03:00
" Unexpected line %s \n " , expr ) ;
}
}
}
fclose ( output ) ;
fclose ( input ) ;
if ( regexp ! = NULL )
xmlRegFreeRegexp ( regexp ) ;
if ( exec ! = NULL )
xmlRegFreeExecCtxt ( exec ) ;
if ( am ! = NULL )
xmlFreeAutomata ( am ) ;
ret = compareFiles ( temp , result ) ;
if ( ret ) {
fprintf ( stderr , " Result for %s failed in %s \n " , filename , result ) ;
res = 1 ;
}
if ( temp ! = NULL ) {
unlink ( temp ) ;
free ( temp ) ;
}
return ( res ) ;
}
2024-06-16 01:04:46 +03:00
# endif /* LIBXML_REGEXP_ENABLED */
2020-07-09 04:21:07 +03:00
2005-07-07 00:41:33 +04:00
/************************************************************************
* *
* Tests Descriptions *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static
testDesc testDescriptions [ ] = {
{ " XML regression tests " ,
oldParseTest , " ./test/* " , " result/ " , " " , NULL ,
0 } ,
{ " XML regression tests on memory " ,
memParseTest , " ./test/* " , " result/ " , " " , NULL ,
0 } ,
{ " XML entity subst regression tests " ,
noentParseTest , " ./test/* " , " result/noent/ " , " " , NULL ,
XML_PARSE_NOENT } ,
{ " XML Namespaces regression tests " ,
errParseTest , " ./test/namespaces/* " , " result/namespaces/ " , " " , " .err " ,
0 } ,
2022-02-22 13:52:38 +03:00
# ifdef LIBXML_VALID_ENABLED
2005-07-07 00:41:33 +04:00
{ " Error cases regression tests " ,
errParseTest , " ./test/errors/*.xml " , " result/errors/ " , " " , " .err " ,
0 } ,
2021-08-26 13:50:41 +03:00
{ " Error cases regression tests from file descriptor " ,
fdParseTest , " ./test/errors/*.xml " , " result/errors/ " , " " , " .err " ,
0 } ,
2020-02-11 15:13:52 +03:00
{ " Error cases regression tests with entity substitution " ,
errParseTest , " ./test/errors/*.xml " , " result/errors/ " , NULL , " .ent " ,
XML_PARSE_NOENT } ,
2017-06-05 16:37:17 +03:00
{ " Error cases regression tests (old 1.0) " ,
errParseTest , " ./test/errors10/*.xml " , " result/errors10/ " , " " , " .err " ,
XML_PARSE_OLD10 } ,
2022-02-22 13:52:38 +03:00
# endif
2005-07-07 00:41:33 +04:00
# ifdef LIBXML_READER_ENABLED
2022-02-22 13:52:38 +03:00
# ifdef LIBXML_VALID_ENABLED
2005-07-07 00:41:33 +04:00
{ " Error cases stream regression tests " ,
streamParseTest , " ./test/errors/*.xml " , " result/errors/ " , NULL , " .str " ,
0 } ,
2022-02-22 13:52:38 +03:00
# endif
2005-07-07 00:41:33 +04:00
{ " Reader regression tests " ,
streamParseTest , " ./test/* " , " result/ " , " .rdr " , NULL ,
0 } ,
{ " Reader entities substitution regression tests " ,
streamParseTest , " ./test/* " , " result/ " , " .rde " , NULL ,
XML_PARSE_NOENT } ,
{ " Reader on memory regression tests " ,
streamMemParseTest , " ./test/* " , " result/ " , " .rdr " , NULL ,
0 } ,
{ " Walker regression tests " ,
walkerParseTest , " ./test/* " , " result/ " , " .rdr " , NULL ,
0 } ,
# endif
# ifdef LIBXML_SAX1_ENABLED
{ " SAX1 callbacks regression tests " ,
saxParseTest , " ./test/* " , " result/ " , " .sax " , NULL ,
XML_PARSE_SAX1 } ,
2017-06-16 22:38:57 +03:00
# endif
2005-07-07 00:41:33 +04:00
{ " SAX2 callbacks regression tests " ,
saxParseTest , " ./test/* " , " result/ " , " .sax2 " , NULL ,
0 } ,
2017-06-16 22:38:57 +03:00
{ " SAX2 callbacks regression tests with entity substitution " ,
saxParseTest , " ./test/* " , " result/noent/ " , " .sax2 " , NULL ,
XML_PARSE_NOENT } ,
2005-07-07 00:41:33 +04:00
# ifdef LIBXML_PUSH_ENABLED
{ " XML push regression tests " ,
pushParseTest , " ./test/* " , " result/ " , " " , NULL ,
0 } ,
2022-11-20 17:36:41 +03:00
{ " XML push boundary tests " ,
pushBoundaryTest , " ./test/* " , " result/ " , " " , NULL ,
0 } ,
2005-07-07 00:41:33 +04:00
# endif
# ifdef LIBXML_HTML_ENABLED
{ " HTML regression tests " ,
errParseTest , " ./test/HTML/* " , " result/HTML/ " , " " , " .err " ,
XML_PARSE_HTML } ,
2021-08-26 13:50:41 +03:00
{ " HTML regression tests from file descriptor " ,
fdParseTest , " ./test/HTML/* " , " result/HTML/ " , " " , " .err " ,
XML_PARSE_HTML } ,
2005-07-07 00:41:33 +04:00
# ifdef LIBXML_PUSH_ENABLED
{ " Push HTML regression tests " ,
pushParseTest , " ./test/HTML/* " , " result/HTML/ " , " " , " .err " ,
XML_PARSE_HTML } ,
2022-11-20 17:36:41 +03:00
{ " Push HTML boundary tests " ,
pushBoundaryTest , " ./test/HTML/* " , " result/HTML/ " , " " , NULL ,
XML_PARSE_HTML } ,
2005-07-07 00:41:33 +04:00
# endif
{ " HTML SAX regression tests " ,
saxParseTest , " ./test/HTML/* " , " result/HTML/ " , " .sax " , NULL ,
XML_PARSE_HTML } ,
# endif
# ifdef LIBXML_VALID_ENABLED
{ " Valid documents regression tests " ,
errParseTest , " ./test/VCM/* " , NULL , NULL , NULL ,
XML_PARSE_DTDVALID } ,
{ " Validity checking regression tests " ,
errParseTest , " ./test/VC/* " , " result/VC/ " , NULL , " " ,
XML_PARSE_DTDVALID } ,
2012-10-25 11:39:39 +04:00
# ifdef LIBXML_READER_ENABLED
{ " Streaming validity checking regression tests " ,
streamParseTest , " ./test/valid/*.xml " , " result/valid/ " , NULL , " .err.rdr " ,
XML_PARSE_DTDVALID } ,
{ " Streaming validity error checking regression tests " ,
streamParseTest , " ./test/VC/* " , " result/VC/ " , NULL , " .rdr " ,
XML_PARSE_DTDVALID } ,
# endif
2005-07-07 00:41:33 +04:00
{ " General documents valid regression tests " ,
errParseTest , " ./test/valid/* " , " result/valid/ " , " " , " .err " ,
XML_PARSE_DTDVALID } ,
# endif
# ifdef LIBXML_XINCLUDE_ENABLED
{ " XInclude regression tests " ,
2022-10-22 17:59:35 +03:00
errParseTest , " ./test/XInclude/docs/* " , " result/XInclude/ " , " " , " .err " ,
2005-07-07 00:41:33 +04:00
XML_PARSE_XINCLUDE } ,
2008-05-12 16:58:46 +04:00
# ifdef LIBXML_READER_ENABLED
2005-07-07 00:41:33 +04:00
{ " XInclude xmlReader regression tests " ,
streamParseTest , " ./test/XInclude/docs/* " , " result/XInclude/ " , " .rdr " ,
2022-10-22 17:59:35 +03:00
" .err " , XML_PARSE_XINCLUDE } ,
2008-05-12 16:58:46 +04:00
# endif
2005-07-07 00:41:33 +04:00
{ " XInclude regression tests stripping include nodes " ,
2022-10-22 17:59:35 +03:00
errParseTest , " ./test/XInclude/docs/* " , " result/XInclude/ " , " " , " .err " ,
2005-07-07 00:41:33 +04:00
XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE } ,
2008-05-12 16:58:46 +04:00
# ifdef LIBXML_READER_ENABLED
2005-07-07 00:41:33 +04:00
{ " XInclude xmlReader regression tests stripping include nodes " ,
streamParseTest , " ./test/XInclude/docs/* " , " result/XInclude/ " , " .rdr " ,
2022-10-22 17:59:35 +03:00
" .err " , XML_PARSE_XINCLUDE | XML_PARSE_NOXINCNODE } ,
2005-07-07 00:41:33 +04:00
# endif
2022-10-22 17:59:35 +03:00
{ " XInclude regression tests without reader " ,
errParseTest , " ./test/XInclude/without-reader/* " , " result/XInclude/ " , " " ,
" .err " , XML_PARSE_XINCLUDE } ,
2008-05-12 16:58:46 +04:00
# endif
2005-07-07 00:41:33 +04:00
# ifdef LIBXML_XPATH_ENABLED
# ifdef LIBXML_DEBUG_ENABLED
{ " XPath expressions regression tests " ,
xpathExprTest , " ./test/XPath/expr/* " , " result/XPath/expr/ " , " " , NULL ,
0 } ,
{ " XPath document queries regression tests " ,
xpathDocTest , " ./test/XPath/docs/* " , NULL , NULL , NULL ,
0 } ,
2022-04-21 04:52:52 +03:00
# ifdef LIBXML_XPTR_ENABLED
2005-07-07 00:41:33 +04:00
{ " XPointer document queries regression tests " ,
xptrDocTest , " ./test/XPath/docs/* " , NULL , NULL , NULL ,
0 } ,
# endif
2022-02-22 13:52:38 +03:00
# ifdef LIBXML_VALID_ENABLED
2005-07-07 00:41:33 +04:00
{ " xml:id regression tests " ,
xmlidDocTest , " ./test/xmlid/* " , " result/xmlid/ " , " " , " .err " ,
0 } ,
# endif
2022-02-22 13:52:38 +03:00
# endif
2005-07-07 00:41:33 +04:00
# endif
{ " URI parsing tests " ,
uriParseTest , " ./test/URI/*.uri " , " result/URI/ " , " " , NULL ,
0 } ,
{ " URI base composition tests " ,
uriBaseTest , " ./test/URI/*.data " , " result/URI/ " , " " , NULL ,
0 } ,
2005-08-07 14:46:19 +04:00
{ " Path URI conversion tests " ,
uriPathTest , NULL , NULL , NULL , NULL ,
0 } ,
2005-07-07 00:41:33 +04:00
# ifdef LIBXML_SCHEMAS_ENABLED
{ " Schemas regression tests " ,
schemasTest , " ./test/schemas/*_*.xsd " , NULL , NULL , NULL ,
0 } ,
{ " Relax-NG regression tests " ,
rngTest , " ./test/relaxng/*.rng " , NULL , NULL , NULL ,
XML_PARSE_DTDATTR | XML_PARSE_NOENT } ,
# ifdef LIBXML_READER_ENABLED
{ " Relax-NG streaming regression tests " ,
rngStreamTest , " ./test/relaxng/*.rng " , NULL , NULL , NULL ,
XML_PARSE_DTDATTR | XML_PARSE_NOENT } ,
# endif
# endif
# ifdef LIBXML_PATTERN_ENABLED
# ifdef LIBXML_READER_ENABLED
{ " Pattern regression tests " ,
patternTest , " ./test/pattern/*.pat " , " result/pattern/ " , NULL , NULL ,
0 } ,
# endif
# endif
# ifdef LIBXML_C14N_ENABLED
{ " C14N with comments regression tests " ,
c14nWithCommentTest , " ./test/c14n/with-comments/*.xml " , NULL , NULL , NULL ,
0 } ,
{ " C14N without comments regression tests " ,
c14nWithoutCommentTest , " ./test/c14n/without-comments/*.xml " , NULL , NULL , NULL ,
0 } ,
{ " C14N exclusive without comments regression tests " ,
c14nExcWithoutCommentTest , " ./test/c14n/exc-without-comments/*.xml " , NULL , NULL , NULL ,
0 } ,
2009-07-09 12:26:22 +04:00
{ " C14N 1.1 without comments regression tests " ,
c14n11WithoutCommentTest , " ./test/c14n/1-1-without-comments/*.xml " , NULL , NULL , NULL ,
0 } ,
2005-07-07 00:41:33 +04:00
# endif
2017-06-16 22:27:47 +03:00
# if defined(LIBXML_THREAD_ENABLED) && defined(LIBXML_CATALOG_ENABLED)
2005-07-07 00:41:33 +04:00
{ " Catalog and Threads regression tests " ,
threadsTest , NULL , NULL , NULL , NULL ,
0 } ,
# endif
2022-04-03 22:39:14 +03:00
{ " SVG parsing regression tests " ,
oldParseTest , " ./test/SVG/*.xml " , " result/SVG/ " , " " , NULL ,
0 } ,
2020-07-09 04:21:07 +03:00
# if defined(LIBXML_REGEXP_ENABLED)
{ " Regexp regression tests " ,
regexpTest , " ./test/regexp/* " , " result/regexp/ " , " " , " .err " ,
0 } ,
2022-09-02 18:26:47 +03:00
{ " Automata regression tests " ,
automataTest , " ./test/automata/* " , " result/automata/ " , " " , NULL ,
0 } ,
2020-07-09 04:21:07 +03:00
# endif
2005-07-07 00:41:33 +04:00
{ NULL , NULL , NULL , NULL , NULL , NULL , 0 }
} ;
/************************************************************************
* *
* The main code driving the tests *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int
launchTests ( testDescPtr tst ) {
int res = 0 , err = 0 ;
size_t i ;
char * result ;
char * error ;
int mem ;
2024-06-07 00:07:16 +03:00
xmlCharEncodingHandlerPtr ebcdicHandler , ibm1141Handler , eucJpHandler ;
2017-10-31 19:17:16 +03:00
ebcdicHandler = xmlGetCharEncodingHandler ( XML_CHAR_ENCODING_EBCDIC ) ;
2024-06-07 00:07:16 +03:00
ibm1141Handler = xmlFindCharEncodingHandler ( " IBM-1141 " ) ;
2024-06-07 01:01:16 +03:00
/*
* When decoding EUC - JP , musl doesn ' t seem to support 0x8F control
* codes .
*/
2018-09-04 18:13:29 +03:00
eucJpHandler = xmlGetCharEncodingHandler ( XML_CHAR_ENCODING_EUC_JP ) ;
2024-06-07 01:01:16 +03:00
if ( eucJpHandler ! = NULL ) {
xmlBufferPtr in , out ;
in = xmlBufferCreateSize ( 10 ) ;
xmlBufferCCat ( in , " \x8f \xe9 \xae " ) ;
out = xmlBufferCreateSize ( 10 ) ;
if ( xmlCharEncInFunc ( eucJpHandler , out , in ) ! = 3 ) {
xmlCharEncCloseFunc ( eucJpHandler ) ;
eucJpHandler = NULL ;
}
xmlBufferFree ( out ) ;
xmlBufferFree ( in ) ;
}
2005-07-07 00:41:33 +04:00
if ( tst = = NULL ) return ( - 1 ) ;
if ( tst - > in ! = NULL ) {
glob_t globbuf ;
globbuf . gl_offs = 0 ;
glob ( tst - > in , GLOB_DOOFFS , NULL , & globbuf ) ;
for ( i = 0 ; i < globbuf . gl_pathc ; i + + ) {
if ( ! checkTestFile ( globbuf . gl_pathv [ i ] ) )
continue ;
2024-06-07 00:07:16 +03:00
if ( ( ( ( ebcdicHandler = = NULL ) | | ( ibm1141Handler = = NULL ) ) & &
2018-09-04 18:13:29 +03:00
( strstr ( globbuf . gl_pathv [ i ] , " ebcdic " ) ! = NULL ) ) | |
( ( eucJpHandler = = NULL ) & &
( strstr ( globbuf . gl_pathv [ i ] , " icu_parse_test " ) ! = NULL ) ) )
2017-10-31 19:17:16 +03:00
continue ;
2005-07-07 00:41:33 +04:00
if ( tst - > suffix ! = NULL ) {
result = resultFilename ( globbuf . gl_pathv [ i ] , tst - > out ,
tst - > suffix ) ;
if ( result = = NULL ) {
fprintf ( stderr , " Out of memory ! \n " ) ;
fatalError ( ) ;
}
} else {
result = NULL ;
}
if ( tst - > err ! = NULL ) {
error = resultFilename ( globbuf . gl_pathv [ i ] , tst - > out ,
tst - > err ) ;
if ( error = = NULL ) {
fprintf ( stderr , " Out of memory ! \n " ) ;
fatalError ( ) ;
}
} else {
error = NULL ;
}
2020-07-09 04:19:13 +03:00
mem = xmlMemUsed ( ) ;
testErrorsSize = 0 ;
testErrors [ 0 ] = 0 ;
res = tst - > func ( globbuf . gl_pathv [ i ] , result , error ,
tst - > options | XML_PARSE_COMPACT ) ;
xmlResetLastError ( ) ;
if ( res ! = 0 ) {
fprintf ( stderr , " File %s generated an error \n " ,
globbuf . gl_pathv [ i ] ) ;
nb_errors + + ;
err + + ;
}
else if ( xmlMemUsed ( ) ! = mem ) {
2024-06-11 12:34:48 +03:00
fprintf ( stderr , " File %s leaked %d bytes \n " ,
globbuf . gl_pathv [ i ] , xmlMemUsed ( ) - mem ) ;
nb_leaks + + ;
err + + ;
2020-07-09 04:19:13 +03:00
}
testErrorsSize = 0 ;
2005-07-07 00:41:33 +04:00
if ( result )
free ( result ) ;
if ( error )
free ( error ) ;
}
globfree ( & globbuf ) ;
} else {
testErrorsSize = 0 ;
testErrors [ 0 ] = 0 ;
res = tst - > func ( NULL , NULL , NULL , tst - > options ) ;
2024-06-11 12:34:48 +03:00
xmlResetLastError ( ) ;
2005-07-07 00:41:33 +04:00
if ( res ! = 0 ) {
nb_errors + + ;
err + + ;
}
}
2017-10-31 19:17:16 +03:00
xmlCharEncCloseFunc ( ebcdicHandler ) ;
2024-06-07 00:07:16 +03:00
xmlCharEncCloseFunc ( ibm1141Handler ) ;
2018-09-04 18:13:29 +03:00
xmlCharEncCloseFunc ( eucJpHandler ) ;
2017-10-31 19:17:16 +03:00
2005-07-07 00:41:33 +04:00
return ( err ) ;
}
2005-07-30 17:18:24 +04:00
static int verbose = 0 ;
2005-08-07 14:46:19 +04:00
static int tests_quiet = 0 ;
2005-07-30 17:18:24 +04:00
static int
runtest ( int i ) {
int ret = 0 , res ;
int old_errors , old_tests , old_leaks ;
old_errors = nb_errors ;
old_tests = nb_tests ;
old_leaks = nb_leaks ;
2005-08-07 14:46:19 +04:00
if ( ( tests_quiet = = 0 ) & & ( testDescriptions [ i ] . desc ! = NULL ) )
2005-07-30 17:18:24 +04:00
printf ( " ## %s \n " , testDescriptions [ i ] . desc ) ;
res = launchTests ( & testDescriptions [ i ] ) ;
if ( res ! = 0 )
ret + + ;
if ( verbose ) {
if ( ( nb_errors = = old_errors ) & & ( nb_leaks = = old_leaks ) )
printf ( " Ran %d tests, no errors \n " , nb_tests - old_tests ) ;
else
printf ( " Ran %d tests, %d errors, %d leaks \n " ,
nb_tests - old_tests ,
nb_errors - old_errors ,
nb_leaks - old_leaks ) ;
}
return ( ret ) ;
}
2005-07-07 00:41:33 +04:00
int
main ( int argc ATTRIBUTE_UNUSED , char * * argv ATTRIBUTE_UNUSED ) {
2005-07-30 17:18:24 +04:00
int i , a , ret = 0 ;
int subset = 0 ;
2005-07-07 00:41:33 +04:00
2022-03-01 00:42:10 +03:00
# if defined(_WIN32)
2017-10-09 03:05:41 +03:00
setvbuf ( stdout , NULL , _IONBF , 0 ) ;
setvbuf ( stderr , NULL , _IONBF , 0 ) ;
# endif
2019-10-14 17:48:32 +03:00
# if defined(_MSC_VER) && _MSC_VER >= 1400 && _MSC_VER < 1900
_set_output_format ( _TWO_DIGIT_EXPONENT ) ;
# endif
2005-07-07 00:41:33 +04:00
initializeLibxml2 ( ) ;
2005-07-30 17:18:24 +04:00
for ( a = 1 ; a < argc ; a + + ) {
if ( ! strcmp ( argv [ a ] , " -v " ) )
verbose = 1 ;
2016-05-22 04:58:30 +03:00
else if ( ! strcmp ( argv [ a ] , " -u " ) )
update_results = 1 ;
2005-08-07 14:46:19 +04:00
else if ( ! strcmp ( argv [ a ] , " -quiet " ) )
tests_quiet = 1 ;
2020-06-04 12:58:04 +03:00
else if ( ! strcmp ( argv [ a ] , " --out " ) )
temp_directory = argv [ + + a ] ;
2005-07-30 17:18:24 +04:00
else {
for ( i = 0 ; testDescriptions [ i ] . func ! = NULL ; i + + ) {
if ( strstr ( testDescriptions [ i ] . desc , argv [ a ] ) ) {
ret + = runtest ( i ) ;
subset + + ;
}
}
}
}
if ( subset = = 0 ) {
for ( i = 0 ; testDescriptions [ i ] . func ! = NULL ; i + + ) {
ret + = runtest ( i ) ;
2005-07-07 00:41:33 +04:00
}
}
if ( ( nb_errors = = 0 ) & & ( nb_leaks = = 0 ) ) {
ret = 0 ;
printf ( " Total %d tests, no errors \n " ,
nb_tests ) ;
} else {
ret = 1 ;
printf ( " Total %d tests, %d errors, %d leaks \n " ,
nb_tests , nb_errors , nb_leaks ) ;
}
xmlCleanupParser ( ) ;
return ( ret ) ;
}
# else /* ! LIBXML_OUTPUT_ENABLED */
int
main ( int argc ATTRIBUTE_UNUSED , char * * argv ATTRIBUTE_UNUSED ) {
fprintf ( stderr , " runtest requires output to be enabled in libxml2 \n " ) ;
2022-04-21 07:03:22 +03:00
return ( 0 ) ;
2005-07-07 00:41:33 +04:00
}
# endif