2023-10-22 13:56:55 +02:00
/*
* testparser . c : Additional parser tests
*
* See Copyright for the status of this software .
*/
2024-06-15 19:13:08 +02:00
# include "libxml.h"
2023-10-22 13:56:55 +02:00
# include <libxml/parser.h>
2023-12-18 19:47:47 +01:00
# include <libxml/xmlreader.h>
2024-01-05 20:31:10 +01:00
# include <libxml/xmlwriter.h>
2024-02-26 13:22:08 +01:00
# include <libxml/HTMLparser.h>
2023-12-18 19:47:47 +01:00
# include <string.h>
2023-10-22 13:56:55 +02:00
2024-01-15 17:15:02 +01:00
static int
testStandaloneWithEncoding ( void ) {
xmlDocPtr doc ;
const char * str =
" <?xml version= \" 1.0 \" standalone= \" yes \" ?> \n "
" <doc></doc> \n " ;
int err = 0 ;
xmlResetLastError ( ) ;
doc = xmlReadDoc ( BAD_CAST str , NULL , " UTF-8 " , 0 ) ;
if ( doc = = NULL ) {
fprintf ( stderr , " xmlReadDoc failed \n " ) ;
err = 1 ;
}
xmlFreeDoc ( doc ) ;
return err ;
}
2023-12-29 18:47:30 +01:00
static int
testUnsupportedEncoding ( void ) {
xmlDocPtr doc ;
const xmlError * error ;
int err = 0 ;
xmlResetLastError ( ) ;
doc = xmlReadDoc ( BAD_CAST " <doc/> " , NULL , " #unsupported " ,
XML_PARSE_NOWARNING ) ;
if ( doc = = NULL ) {
fprintf ( stderr , " xmlReadDoc failed with unsupported encoding \n " ) ;
err = 1 ;
}
xmlFreeDoc ( doc ) ;
error = xmlGetLastError ( ) ;
if ( error - > code ! = XML_ERR_UNSUPPORTED_ENCODING | |
error - > level ! = XML_ERR_WARNING | |
strcmp ( error - > message , " Unsupported encoding: #unsupported \n " ) ! = 0 )
{
fprintf ( stderr , " xmlReadDoc failed to raise correct error \n " ) ;
err = 1 ;
}
return err ;
}
2024-04-30 15:58:01 +02:00
static int
testNodeGetContent ( void ) {
xmlDocPtr doc ;
xmlChar * content ;
int err = 0 ;
doc = xmlReadDoc ( BAD_CAST " <doc/> " , NULL , NULL , 0 ) ;
xmlAddChild ( doc - > children , xmlNewReference ( doc , BAD_CAST " lt " ) ) ;
content = xmlNodeGetContent ( ( xmlNodePtr ) doc ) ;
if ( strcmp ( ( char * ) content , " < " ) ! = 0 ) {
fprintf ( stderr , " xmlNodeGetContent failed \n " ) ;
err = 1 ;
}
xmlFree ( content ) ;
xmlFreeDoc ( doc ) ;
return err ;
}
2023-12-25 04:33:00 +01:00
# ifdef LIBXML_SAX1_ENABLED
static int
testBalancedChunk ( void ) {
xmlNodePtr list ;
xmlNodePtr elem ;
int ret ;
int err = 0 ;
ret = xmlParseBalancedChunkMemory ( NULL , NULL , NULL , 0 ,
2024-03-17 16:23:31 +01:00
BAD_CAST " start <node xml:lang='en'>abc</node> end " , & list ) ;
2023-12-25 04:33:00 +01:00
if ( ( ret ! = XML_ERR_OK ) | |
( list = = NULL ) | |
( ( elem = list - > next ) = = NULL ) | |
( elem - > type ! = XML_ELEMENT_NODE ) | |
2024-03-17 16:23:31 +01:00
( elem - > nsDef = = NULL ) | |
( ! xmlStrEqual ( elem - > nsDef - > href , XML_XML_NAMESPACE ) ) ) {
2023-12-25 04:33:00 +01:00
fprintf ( stderr , " xmlParseBalancedChunkMemory failed \n " ) ;
err = 1 ;
}
xmlFreeNodeList ( list ) ;
return ( err ) ;
}
# endif
2023-10-22 13:56:55 +02:00
# ifdef LIBXML_PUSH_ENABLED
static int
testHugePush ( void ) {
xmlParserCtxtPtr ctxt ;
int err , i ;
ctxt = xmlCreatePushParserCtxt ( NULL , NULL , NULL , 0 , NULL ) ;
/*
* Push parse a document larger than XML_MAX_LOOKUP_LIMIT
* ( 10 , 000 , 000 bytes ) . This mainly tests whether shrinking the
* buffer works when push parsing .
*/
xmlParseChunk ( ctxt , " <doc> " , 5 , 0 ) ;
for ( i = 0 ; i < 1000000 ; i + + )
xmlParseChunk ( ctxt , " <elem>text</elem> " , 17 , 0 ) ;
xmlParseChunk ( ctxt , " </doc> " , 6 , 1 ) ;
err = ctxt - > wellFormed ? 0 : 1 ;
xmlFreeDoc ( ctxt - > myDoc ) ;
xmlFreeParserCtxt ( ctxt ) ;
return err ;
}
2023-10-28 03:04:59 +02:00
static int
testHugeEncodedChunk ( void ) {
xmlBufferPtr buf ;
xmlChar * chunk ;
xmlParserCtxtPtr ctxt ;
int err , i ;
/*
* Test the push parser with a built - in encoding handler like ISO - 8859 - 1
* and a chunk larger than the initial decoded buffer ( currently 4 KB ) .
*/
buf = xmlBufferCreate ( ) ;
xmlBufferCat ( buf ,
BAD_CAST " <?xml version='1.0' encoding='ISO-8859-1'?> \n " ) ;
xmlBufferCat ( buf , BAD_CAST " <doc><!-- " ) ;
for ( i = 0 ; i < 2000 ; i + + )
xmlBufferCat ( buf , BAD_CAST " 0123456789 " ) ;
xmlBufferCat ( buf , BAD_CAST " --></doc> " ) ;
chunk = xmlBufferDetach ( buf ) ;
xmlBufferFree ( buf ) ;
ctxt = xmlCreatePushParserCtxt ( NULL , NULL , NULL , 0 , NULL ) ;
xmlParseChunk ( ctxt , ( char * ) chunk , xmlStrlen ( chunk ) , 0 ) ;
xmlParseChunk ( ctxt , NULL , 0 , 1 ) ;
err = ctxt - > wellFormed ? 0 : 1 ;
xmlFreeDoc ( ctxt - > myDoc ) ;
xmlFreeParserCtxt ( ctxt ) ;
xmlFree ( chunk ) ;
return err ;
}
2024-02-26 13:22:08 +01:00
# ifdef LIBXML_HTML_ENABLED
static int
testHtmlPushWithEncoding ( void ) {
htmlParserCtxtPtr ctxt ;
htmlDocPtr doc ;
htmlNodePtr node ;
int err = 0 ;
ctxt = htmlCreatePushParserCtxt ( NULL , NULL , NULL , 0 , NULL ,
XML_CHAR_ENCODING_UTF8 ) ;
htmlParseChunk ( ctxt , " - \xC3 \xA4 - " , 4 , 1 ) ;
doc = ctxt - > myDoc ;
if ( ! xmlStrEqual ( doc - > encoding , BAD_CAST " UTF-8 " ) ) {
fprintf ( stderr , " testHtmlPushWithEncoding failed \n " ) ;
err = 1 ;
}
node = xmlDocGetRootElement ( doc ) - > children - > children - > children ;
if ( ! xmlStrEqual ( node - > content , BAD_CAST " - \xC3 \xA4 - " ) ) {
fprintf ( stderr , " testHtmlPushWithEncoding failed \n " ) ;
err = 1 ;
}
xmlFreeDoc ( doc ) ;
htmlFreeParserCtxt ( ctxt ) ;
return err ;
}
# endif
2023-10-22 13:56:55 +02:00
# endif
2024-02-26 15:14:28 +01:00
# ifdef LIBXML_READER_ENABLED
static int
testReaderEncoding ( void ) {
xmlBuffer * buf ;
xmlTextReader * reader ;
xmlChar * xml ;
const xmlChar * encoding ;
int err = 0 ;
int i ;
buf = xmlBufferCreate ( ) ;
xmlBufferCCat ( buf , " <?xml version='1.0' encoding='ISO-8859-1'?> \n " ) ;
xmlBufferCCat ( buf , " <doc> " ) ;
for ( i = 0 ; i < 8192 ; i + + )
xmlBufferCCat ( buf , " x " ) ;
xmlBufferCCat ( buf , " </doc> " ) ;
xml = xmlBufferDetach ( buf ) ;
xmlBufferFree ( buf ) ;
reader = xmlReaderForDoc ( BAD_CAST xml , NULL , NULL , 0 ) ;
xmlTextReaderRead ( reader ) ;
encoding = xmlTextReaderConstEncoding ( reader ) ;
if ( ! xmlStrEqual ( encoding , BAD_CAST " ISO-8859-1 " ) ) {
fprintf ( stderr , " testReaderEncoding failed \n " ) ;
err = 1 ;
}
xmlFreeTextReader ( reader ) ;
xmlFree ( xml ) ;
return err ;
}
2024-04-18 14:21:19 +02:00
static int
testReaderContent ( void ) {
xmlTextReader * reader ;
const xmlChar * xml = BAD_CAST " <d>x<e>y</e><f>z</f></d> " ;
xmlChar * string ;
int err = 0 ;
reader = xmlReaderForDoc ( xml , NULL , NULL , 0 ) ;
xmlTextReaderRead ( reader ) ;
string = xmlTextReaderReadOuterXml ( reader ) ;
if ( ! xmlStrEqual ( string , xml ) ) {
fprintf ( stderr , " xmlTextReaderReadOuterXml failed \n " ) ;
err = 1 ;
}
xmlFree ( string ) ;
string = xmlTextReaderReadInnerXml ( reader ) ;
if ( ! xmlStrEqual ( string , BAD_CAST " x<e>y</e><f>z</f> " ) ) {
fprintf ( stderr , " xmlTextReaderReadInnerXml failed \n " ) ;
err = 1 ;
}
xmlFree ( string ) ;
string = xmlTextReaderReadString ( reader ) ;
if ( ! xmlStrEqual ( string , BAD_CAST " xyz " ) ) {
fprintf ( stderr , " xmlTextReaderReadString failed \n " ) ;
err = 1 ;
}
xmlFree ( string ) ;
xmlFreeTextReader ( reader ) ;
return err ;
}
2024-02-26 15:14:28 +01:00
# ifdef LIBXML_XINCLUDE_ENABLED
2023-12-18 19:47:47 +01:00
typedef struct {
char * message ;
int code ;
} testReaderErrorCtxt ;
static void
testReaderError ( void * arg , const char * msg ,
xmlParserSeverities severity ATTRIBUTE_UNUSED ,
xmlTextReaderLocatorPtr locator ATTRIBUTE_UNUSED ) {
testReaderErrorCtxt * ctxt = arg ;
if ( ctxt - > message ! = NULL )
xmlFree ( ctxt - > message ) ;
ctxt - > message = xmlMemStrdup ( msg ) ;
}
static void
testStructuredReaderError ( void * arg , const xmlError * error ) {
testReaderErrorCtxt * ctxt = arg ;
if ( ctxt - > message ! = NULL )
xmlFree ( ctxt - > message ) ;
ctxt - > message = xmlMemStrdup ( error - > message ) ;
ctxt - > code = error - > code ;
}
static int
testReaderXIncludeError ( void ) {
/*
* Test whether XInclude errors are reported to the custom error
* handler of a reader .
*/
const char * doc =
" <doc xmlns:xi='http://www.w3.org/2001/XInclude'> \n "
" <xi:include/> \n "
" </doc> \n " ;
xmlTextReader * reader ;
testReaderErrorCtxt errorCtxt ;
int err = 0 ;
reader = xmlReaderForDoc ( BAD_CAST doc , NULL , NULL , XML_PARSE_XINCLUDE ) ;
xmlTextReaderSetErrorHandler ( reader , testReaderError , & errorCtxt ) ;
errorCtxt . message = NULL ;
errorCtxt . code = 0 ;
while ( xmlTextReaderRead ( reader ) > 0 )
;
if ( errorCtxt . message = = NULL | |
2023-12-22 21:38:50 +01:00
strstr ( errorCtxt . message , " href or xpointer " ) = = NULL ) {
2023-12-18 19:47:47 +01:00
fprintf ( stderr , " xmlTextReaderSetErrorHandler failed \n " ) ;
err = 1 ;
}
xmlFree ( errorCtxt . message ) ;
xmlFreeTextReader ( reader ) ;
reader = xmlReaderForDoc ( BAD_CAST doc , NULL , NULL , XML_PARSE_XINCLUDE ) ;
xmlTextReaderSetStructuredErrorHandler ( reader , testStructuredReaderError ,
& errorCtxt ) ;
errorCtxt . message = NULL ;
errorCtxt . code = 0 ;
while ( xmlTextReaderRead ( reader ) > 0 )
;
2023-12-22 21:38:50 +01:00
if ( errorCtxt . code ! = XML_XINCLUDE_NO_HREF | |
2023-12-18 19:47:47 +01:00
errorCtxt . message = = NULL | |
2023-12-22 21:38:50 +01:00
strstr ( errorCtxt . message , " href or xpointer " ) = = NULL ) {
2023-12-18 19:47:47 +01:00
fprintf ( stderr , " xmlTextReaderSetStructuredErrorHandler failed \n " ) ;
err = 1 ;
}
xmlFree ( errorCtxt . message ) ;
xmlFreeTextReader ( reader ) ;
return err ;
}
# endif
2024-02-26 15:14:28 +01:00
# endif
2023-12-18 19:47:47 +01:00
2024-01-05 20:31:10 +01:00
# ifdef LIBXML_WRITER_ENABLED
static int
testWriterIOWrite ( void * ctxt , const char * data , int len ) {
( void ) ctxt ;
( void ) data ;
return len ;
}
static int
testWriterIOClose ( void * ctxt ) {
( void ) ctxt ;
return XML_IO_ENAMETOOLONG ;
}
static int
testWriterClose ( void ) {
xmlOutputBufferPtr out ;
xmlTextWriterPtr writer ;
int err = 0 ;
int result ;
out = xmlOutputBufferCreateIO ( testWriterIOWrite , testWriterIOClose ,
NULL , NULL ) ;
writer = xmlNewTextWriter ( out ) ;
xmlTextWriterStartDocument ( writer , " 1.0 " , " UTF-8 " , NULL ) ;
xmlTextWriterStartElement ( writer , BAD_CAST " elem " ) ;
xmlTextWriterEndElement ( writer ) ;
xmlTextWriterEndDocument ( writer ) ;
result = xmlTextWriterClose ( writer ) ;
if ( result ! = XML_IO_ENAMETOOLONG ) {
fprintf ( stderr , " xmlTextWriterClose reported wrong error %d \n " ,
result ) ;
err = 1 ;
}
xmlFreeTextWriter ( writer ) ;
return err ;
}
# endif
2023-10-22 13:56:55 +02:00
int
main ( void ) {
int err = 0 ;
2024-01-15 17:15:02 +01:00
err | = testStandaloneWithEncoding ( ) ;
2023-12-29 18:47:30 +01:00
err | = testUnsupportedEncoding ( ) ;
2024-04-30 15:58:01 +02:00
err | = testNodeGetContent ( ) ;
2023-12-25 04:33:00 +01:00
# ifdef LIBXML_SAX1_ENABLED
err | = testBalancedChunk ( ) ;
# endif
2023-10-22 13:56:55 +02:00
# ifdef LIBXML_PUSH_ENABLED
err | = testHugePush ( ) ;
2023-10-28 03:04:59 +02:00
err | = testHugeEncodedChunk ( ) ;
2024-02-26 13:22:08 +01:00
# ifdef LIBXML_HTML_ENABLED
err | = testHtmlPushWithEncoding ( ) ;
# endif
2023-10-22 13:56:55 +02:00
# endif
2024-02-26 15:14:28 +01:00
# ifdef LIBXML_READER_ENABLED
err | = testReaderEncoding ( ) ;
2024-04-18 14:21:19 +02:00
err | = testReaderContent ( ) ;
2024-02-26 15:14:28 +01:00
# ifdef LIBXML_XINCLUDE_ENABLED
2023-12-18 19:47:47 +01:00
err | = testReaderXIncludeError ( ) ;
# endif
2024-02-26 15:14:28 +01:00
# endif
2024-01-05 20:31:10 +01:00
# ifdef LIBXML_WRITER_ENABLED
err | = testWriterClose ( ) ;
# endif
2023-10-22 13:56:55 +02:00
return err ;
}