merged tag ooo/OOO330_m14
[LibreOffice.git] / extensions / test / sax / testwriter.cxx
blobde606006ef90165b7a7d1e945a9889af41cee3e2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
31 //#include <tools/presys.h>
32 #include <vector>
33 //#include <tools/postsys.h>
34 #include <smart/com/sun/star/test/XSimpleTest.hxx>
35 #include <smart/com/sun/star/lang/XMultiServiceFactory.hxx> // for the multiservice-factories
37 #include <stdio.h>
39 #include <smart/com/sun/star/io/XActiveDataSource.hxx>
40 #include <smart/com/sun/star/io/XOutputStream.hxx>
41 #include <smart/com/sun/star/xml/sax/SAXParseException.hxx>
42 #include <smart/com/sun/star/xml/sax/XParser.hxx>
43 #include <smart/com/sun/star/xml/sax/XExtendedDocumentHandler.hxx>
45 #include <rtl/wstring.hxx>
46 #include <osl/time.h>
47 #include <usr/weak.hxx>
48 #include <tools/string.hxx>
50 #include <usr/factoryhlp.hxx>
52 #include <usr/reflserv.hxx> // for EXTERN_SERVICE_CALLTYPE
54 using namespace std;
55 using namespace rtl;
56 using namespace vos;
57 using namespace usr;
59 #define BUILD_ERROR(expr, Message)\
61 m_seqErrors.realloc( m_seqErrors.getLen() + 1 ); \
62 m_seqExceptions.realloc( m_seqExceptions.getLen() + 1 ); \
63 String str; \
64 str += __FILE__;\
65 str += " "; \
66 str += "(" ; \
67 str += __LINE__ ;\
68 str += ")\n";\
69 str += "[ " ; \
70 str += #expr; \
71 str += " ] : " ; \
72 str += Message; \
73 m_seqErrors.getArray()[ m_seqErrors.getLen()-1] = StringToUString( str , CHARSET_SYSTEM ); \
75 ((void)0)
78 #define WARNING_ASSERT(expr, Message) \
79 if( ! (expr) ) { \
80 m_seqWarnings.realloc( m_seqErrors.getLen() +1 ); \
81 String str;\
82 str += __FILE__;\
83 str += " "; \
84 str += "(" ; \
85 str += __LINE__ ;\
86 str += ")\n";\
87 str += "[ " ; \
88 str += #expr; \
89 str += " ] : " ; \
90 str += Message; \
91 m_seqWarnings.getArray()[ m_seqWarnings.getLen()-1] = StringToUString( str , CHARSET_SYSTEM ); \
92 return; \
94 ((void)0)
96 #define ERROR_ASSERT(expr, Message) \
97 if( ! (expr) ) { \
98 BUILD_ERROR(expr, Message );\
99 return; \
101 ((void)0)
103 #define ERROR_EXCEPTION_ASSERT(expr, Message, Exception) \
104 if( !(expr)) { \
105 BUILD_ERROR(expr,Message);\
106 m_seqExceptions.getArray()[ m_seqExceptions.getLen()-1] = UsrAny( Exception );\
107 return; \
109 ((void)0)
111 /****
112 * test szenarios :
116 ****/
119 class OFileWriter :
120 public XOutputStream,
121 public OWeakObject
123 public:
124 OFileWriter( char *pcFile ) { strcpy( m_pcFile , pcFile ); m_f = 0; }
127 public: // refcounting
128 BOOL queryInterface( Uik aUik, XInterfaceRef & rOut )
130 if( XOutputStream::getSmartUik() == aUik ) {
131 rOut = (XOutputStream *) this;
133 else return OWeakObject::queryInterface( aUik , rOut );
135 return TRUE;
137 void acquire() { OWeakObject::acquire(); }
138 void release() { OWeakObject::release(); }
139 void* getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }
141 public:
142 virtual void writeBytes(const Sequence< BYTE >& aData)
143 THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) );
144 virtual void flush(void)
145 THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) );
146 virtual void closeOutput(void)
147 THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) );
150 private:
151 char m_pcFile[256];
152 FILE *m_f;
156 void OFileWriter::writeBytes(const Sequence< BYTE >& aData)
157 THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) )
159 if( ! m_f ) {
160 m_f = fopen( m_pcFile , "w" );
163 fwrite( aData.getConstArray() , 1 , aData.getLen() , m_f );
168 void OFileWriter::flush(void)
169 THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) )
171 fflush( m_f );
174 void OFileWriter::closeOutput(void)
175 THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) )
177 fclose( m_f );
178 m_f = 0;
182 class OSaxWriterTest :
183 public XSimpleTest,
184 public OWeakObject
186 public:
187 OSaxWriterTest( const XMultiServiceFactoryRef & rFactory ) : m_rFactory( rFactory )
191 ~OSaxWriterTest() {}
193 public: // refcounting
194 BOOL queryInterface( Uik aUik, XInterfaceRef & rOut );
195 void acquire() { OWeakObject::acquire(); }
196 void release() { OWeakObject::release(); }
197 void* getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }
199 public:
200 virtual void testInvariant(const UString& TestName, const XInterfaceRef& TestObject)
201 THROWS( ( IllegalArgumentException,
202 UsrSystemException) );
204 virtual INT32 test( const UString& TestName,
205 const XInterfaceRef& TestObject,
206 INT32 hTestHandle) THROWS( ( IllegalArgumentException,
207 UsrSystemException) );
209 virtual BOOL testPassed(void) THROWS( ( UsrSystemException) );
210 virtual Sequence< UString > getErrors(void) THROWS( (UsrSystemException) );
211 virtual Sequence< UsrAny > getErrorExceptions(void) THROWS( (UsrSystemException) );
212 virtual Sequence< UString > getWarnings(void) THROWS( (UsrSystemException) );
214 private:
215 void testSimple( const XExtendedDocumentHandlerRef &r );
216 void testExceptions( const XExtendedDocumentHandlerRef &r );
217 void testDTD( const XExtendedDocumentHandlerRef &r );
218 void testPerformance( const XExtendedDocumentHandlerRef &r );
219 void writeParagraph( const XExtendedDocumentHandlerRef &r , const UString & s);
221 private:
222 Sequence<UsrAny> m_seqExceptions;
223 Sequence<UString> m_seqErrors;
224 Sequence<UString> m_seqWarnings;
225 XMultiServiceFactoryRef m_rFactory;
231 /*----------------------------------------
233 * Attributlist implementation
235 *----------------------------------------*/
236 struct AttributeListImpl_impl;
237 class AttributeListImpl :
238 public XAttributeList,
239 public OWeakObject
241 public:
242 AttributeListImpl();
243 AttributeListImpl( const AttributeListImpl & );
244 ~AttributeListImpl();
246 public:
247 BOOL queryInterface( Uik aUik, XInterfaceRef & rOut );
248 void acquire() { OWeakObject::acquire(); }
249 void release() { OWeakObject::release(); }
250 void* getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }
252 public:
253 virtual INT16 getLength(void) THROWS( (UsrSystemException) );
254 virtual UString getNameByIndex(INT16 i) THROWS( (UsrSystemException) );
255 virtual UString getTypeByIndex(INT16 i) THROWS( (UsrSystemException) );
256 virtual UString getTypeByName(const UString& aName) THROWS( (UsrSystemException) );
257 virtual UString getValueByIndex(INT16 i) THROWS( (UsrSystemException) );
258 virtual UString getValueByName(const UString& aName) THROWS( (UsrSystemException) );
260 public:
261 void addAttribute( const UString &sName , const UString &sType , const UString &sValue );
262 void clear();
264 private:
265 struct AttributeListImpl_impl *m_pImpl;
269 struct TagAttribute
271 TagAttribute(){}
272 TagAttribute( const UString &sName, const UString &sType , const UString &sValue )
274 this->sName = sName;
275 this->sType = sType;
276 this->sValue = sValue;
279 UString sName;
280 UString sType;
281 UString sValue;
284 struct AttributeListImpl_impl
286 AttributeListImpl_impl()
288 // performance improvement during adding
289 vecAttribute.reserve(20);
291 vector<struct TagAttribute> vecAttribute;
296 INT16 AttributeListImpl::getLength(void) THROWS( (UsrSystemException) )
298 return m_pImpl->vecAttribute.size();
302 AttributeListImpl::AttributeListImpl( const AttributeListImpl &r )
304 m_pImpl = new AttributeListImpl_impl;
305 *m_pImpl = *(r.m_pImpl);
308 UString AttributeListImpl::getNameByIndex(INT16 i) THROWS( (UsrSystemException) )
310 if( i < m_pImpl->vecAttribute.size() ) {
311 return m_pImpl->vecAttribute[i].sName;
313 return UString();
317 UString AttributeListImpl::getTypeByIndex(INT16 i) THROWS( (UsrSystemException) )
319 if( i < m_pImpl->vecAttribute.size() ) {
320 return m_pImpl->vecAttribute[i].sType;
322 return UString();
325 UString AttributeListImpl::getValueByIndex(INT16 i) THROWS( (UsrSystemException) )
327 if( i < m_pImpl->vecAttribute.size() ) {
328 return m_pImpl->vecAttribute[i].sValue;
330 return UString();
334 UString AttributeListImpl::getTypeByName( const UString& sName ) THROWS( (UsrSystemException) )
336 vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
338 for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
339 if( (*ii).sName == sName ) {
340 return (*ii).sType;
343 return UString();
346 UString AttributeListImpl::getValueByName(const UString& sName) THROWS( (UsrSystemException) )
348 vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
350 for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
351 if( (*ii).sName == sName ) {
352 return (*ii).sValue;
355 return UString();
359 BOOL AttributeListImpl::queryInterface( Uik aUik, XInterfaceRef & rOut )
361 if( aUik == XAttributeList::getSmartUik() ) {
362 rOut = (XAttributeList * )this;
364 else {
365 return OWeakObject::queryInterface( aUik , rOut );
367 return TRUE;
371 AttributeListImpl::AttributeListImpl()
373 m_pImpl = new AttributeListImpl_impl;
378 AttributeListImpl::~AttributeListImpl()
380 delete m_pImpl;
384 void AttributeListImpl::addAttribute( const UString &sName ,
385 const UString &sType ,
386 const UString &sValue )
388 m_pImpl->vecAttribute.push_back( TagAttribute( sName , sType , sValue ) );
391 void AttributeListImpl::clear()
393 vector<struct TagAttribute> dummy;
394 m_pImpl->vecAttribute.swap( dummy );
396 OSL_ASSERT( ! getLength() );
410 * for external binding
414 XInterfaceRef OSaxWriterTest_CreateInstance( const XMultiServiceFactoryRef & rSMgr ) THROWS((Exception))
416 OSaxWriterTest *p = new OSaxWriterTest( rSMgr );
417 XInterfaceRef xService = *p;
418 return xService;
421 UString OSaxWriterTest_getServiceName( ) THROWS( () )
423 return L"test.com.sun.star.xml.sax.Writer";
426 UString OSaxWriterTest_getImplementationName( ) THROWS( () )
428 return L"test.extensions.xml.sax.Writer";
431 Sequence<UString> OSaxWriterTest_getSupportedServiceNames( ) THROWS( () )
433 Sequence<UString> aRet(1);
435 aRet.getArray()[0] = OSaxWriterTest_getImplementationName( );
437 return aRet;
441 BOOL OSaxWriterTest::queryInterface( Uik uik , XInterfaceRef &rOut )
443 if( XSimpleTest::getSmartUik() == uik ) {
444 rOut = (XSimpleTest *) this;
446 else {
447 return OWeakObject::queryInterface( uik , rOut );
449 return TRUE;
453 void OSaxWriterTest::testInvariant( const UString& TestName, const XInterfaceRef& TestObject )
454 THROWS( ( IllegalArgumentException,
455 UsrSystemException) )
457 if( L"com.sun.star.xml.sax.Writer" == TestName ) {
458 XDocumentHandlerRef doc( TestObject , USR_QUERY );
459 XExtendedDocumentHandlerRef ext( TestObject , USR_QUERY );
460 XActiveDataSourceRef source( TestObject , USR_QUERY );
462 ERROR_ASSERT( doc.is() , "XDocumentHandler cannot be queried" );
463 ERROR_ASSERT( ext.is() , "XExtendedDocumentHandler cannot be queried" );
464 ERROR_ASSERT( source.is() , "XActiveDataSource cannot be queried" );
466 else {
467 BUILD_ERROR( 0 , "wrong test" );
472 INT32 OSaxWriterTest::test( const UString& TestName,
473 const XInterfaceRef& TestObject,
474 INT32 hTestHandle) THROWS( ( IllegalArgumentException,
475 UsrSystemException) )
477 if( L"com.sun.star.xml.sax.Writer" == TestName ) {
478 try {
479 if( 0 == hTestHandle ) {
480 testInvariant( TestName , TestObject );
482 else {
484 XExtendedDocumentHandlerRef writer( TestObject , USR_QUERY );
486 if( 1 == hTestHandle ) {
487 testSimple( writer );
489 else if( 2 == hTestHandle ) {
490 testExceptions( writer );
492 else if( 3 == hTestHandle ) {
493 testDTD( writer );
495 else if( 4 == hTestHandle ) {
496 testPerformance( writer );
500 catch( Exception& e ) {
501 BUILD_ERROR( 0 , UStringToString( e.getName() , CHARSET_SYSTEM ).GetCharStr() );
503 catch(...) {
504 BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" );
507 hTestHandle ++;
509 if( hTestHandle >= 5) {
510 // all tests finished.
511 hTestHandle = -1;
514 else {
515 BUILD_ERROR( 0 , "service not supported by test." );
517 return hTestHandle;
522 BOOL OSaxWriterTest::testPassed(void) THROWS( (UsrSystemException) )
524 return m_seqErrors.getLen() == 0;
528 Sequence< UString > OSaxWriterTest::getErrors(void) THROWS( (UsrSystemException) )
530 return m_seqErrors;
534 Sequence< UsrAny > OSaxWriterTest::getErrorExceptions(void) THROWS( (UsrSystemException) )
536 return m_seqExceptions;
540 Sequence< UString > OSaxWriterTest::getWarnings(void) THROWS( (UsrSystemException) )
542 return m_seqWarnings;
545 void OSaxWriterTest::writeParagraph( const XExtendedDocumentHandlerRef &r , const UString & s)
547 int nMax = s.len();
548 int nStart = 0;
550 Sequence<UINT16> seq( s.len() );
551 memcpy( seq.getArray() , s.getStr() , s.len() * sizeof( UINT16 ) );
553 for( int n = 1 ; n < nMax ; n++ ){
554 if( 32 == seq.getArray()[n] ) {
555 r->allowLineBreak();
556 r->characters( s.copy( nStart , n - nStart ) );
557 nStart = n;
560 r->allowLineBreak();
561 r->characters( s.copy( nStart , n - nStart ) );
568 void OSaxWriterTest::testSimple( const XExtendedDocumentHandlerRef &r )
570 UString testParagraph = L"Dies ist ein bloeder Test um zu uberpruefen, ob der SAXWriter "
571 L"wohl Zeilenumbrueche halbwegs richtig macht oder ob er die Zeile "
572 L"bis zum bitteren Ende schreibt.";
574 OFileWriter *pw = new OFileWriter("output.xml");
575 AttributeListImpl *pList = new AttributeListImpl;
577 XAttributeListRef rList( (XAttributeList *) pList , USR_QUERY );
578 XOutputStreamRef ref( ( XOutputStream * ) pw , USR_QUERY );
580 XActiveDataSourceRef source( r , USR_QUERY );
582 ERROR_ASSERT( ref.is() , "no output stream" );
583 ERROR_ASSERT( source.is() , "no active data source" );
585 source->setOutputStream( ref );
587 r->startDocument();
589 pList->addAttribute( L"Arg1" , L"CDATA" , L"bla\n u" );
590 pList->addAttribute( L"Arg2" , L"CDATA" , L"blub" );
592 r->startElement( L"tag1" , rList );
593 r->ignorableWhitespace( L"" );
595 r->characters( L"huhu" );
596 r->ignorableWhitespace( L"" );
598 r->startElement( L"hi" , rList );
599 r->ignorableWhitespace( L"" );
601 // the enpassant must be converted & -> &amp;
602 r->characters( L"&#252;" );
604 // Test added for mib. Tests if errors during conversions occurs
605 r->ignorableWhitespace( UString() );
606 sal_Char array[256];
607 for( sal_Int32 n = 32 ; n < 254 ; n ++ ) {
608 array[n-32] = n;
610 array[254-32] = 0;
611 r->characters(
612 StringToUString( array , RTL_TEXTENCODING_SYMBOL )
614 r->ignorableWhitespace( UString() );
616 // '>' must not be converted
617 r->startCDATA();
618 r->characters( L">fsfsdf<" );
619 r->endCDATA();
620 r->ignorableWhitespace( UString() );
622 writeParagraph( r , testParagraph );
625 r->ignorableWhitespace( UString() );
626 r->comment( L"Dies ist ein Kommentar !" );
627 r->ignorableWhitespace( UString() );
629 r->startElement( L"emptytagtest" , rList );
630 r->endElement( L"emptytagtest" );
632 r->endElement( L"hi" );
633 r->ignorableWhitespace( L"" );
635 r->endElement( L"tag1" );
636 r->endDocument();
640 void OSaxWriterTest::testExceptions( const XExtendedDocumentHandlerRef & r )
643 OFileWriter *pw = new OFileWriter("output2.xml");
644 AttributeListImpl *pList = new AttributeListImpl;
646 XAttributeListRef rList( (XAttributeList *) pList , USR_QUERY );
647 XOutputStreamRef ref( ( XOutputStream * ) pw , USR_QUERY );
649 XActiveDataSourceRef source( r , USR_QUERY );
651 ERROR_ASSERT( ref.is() , "no output stream" );
652 ERROR_ASSERT( source.is() , "no active data source" );
654 source->setOutputStream( ref );
656 { // startDocument must be called before start element
657 BOOL bException = TRUE;
658 try {
659 r->startElement( L"huhu" , rList );
660 bException = FALSE;
662 catch( SAXException& e ) {
665 ERROR_ASSERT( bException , "expected exception not thrown !" );
668 r->startDocument();
670 r->startElement( L"huhu" , rList );
671 r->startCDATA();
674 BOOL bException = TRUE;
675 try {
676 r->startElement( L"huhu" , rList );
677 bException = FALSE;
679 catch( SAXException& e ) {
682 ERROR_ASSERT( bException , "expected exception not thrown !" );
685 r->endCDATA();
686 r->endElement( L"hi" );
688 r->endDocument();
692 void OSaxWriterTest::testDTD(const XExtendedDocumentHandlerRef &r )
694 OFileWriter *pw = new OFileWriter("outputDTD.xml");
695 AttributeListImpl *pList = new AttributeListImpl;
697 XAttributeListRef rList( (XAttributeList *) pList , USR_QUERY );
698 XOutputStreamRef ref( ( XOutputStream * ) pw , USR_QUERY );
700 XActiveDataSourceRef source( r , USR_QUERY );
702 ERROR_ASSERT( ref.is() , "no output stream" );
703 ERROR_ASSERT( source.is() , "no active data source" );
705 source->setOutputStream( ref );
708 r->startDocument();
709 r->unknown( L"<!DOCTYPE iCalendar >\n" );
710 r->startElement( L"huhu" , rList );
712 r->endElement( L"huhu" );
713 r->endDocument();
716 void OSaxWriterTest::testPerformance(const XExtendedDocumentHandlerRef &r )
718 OFileWriter *pw = new OFileWriter("testPerformance.xml");
719 AttributeListImpl *pList = new AttributeListImpl;
721 UString testParagraph = L"Dies ist ein bloeder Test um zu uberpruefen, ob der SAXWriter "
722 L"wohl > Zeilenumbrueche halbwegs richtig macht oder ob er die Zeile "
723 L"bis zum bitteren Ende schreibt.";
726 XAttributeListRef rList( (XAttributeList *) pList , USR_QUERY );
727 XOutputStreamRef ref( ( XOutputStream * ) pw , USR_QUERY );
729 XActiveDataSourceRef source( r , USR_QUERY );
731 ERROR_ASSERT( ref.is() , "no output stream" );
732 ERROR_ASSERT( source.is() , "no active data source" );
734 source->setOutputStream( ref );
736 TimeValue aStartTime, aEndTime;
737 osl_getSystemTime( &aStartTime );
740 r->startDocument();
741 // just write a bunch of xml tags !
742 // for performance testing
743 sal_Int32 i2;
744 for( i2 = 0 ; i2 < 15 ; i2 ++ )
746 r->startElement( UString( L"tag" ) + UString::valueOf( i2 ), rList );
747 for( sal_Int32 i = 0 ; i < 450 ; i ++ )
749 r->ignorableWhitespace( L"");
750 r->startElement( L"huhu" , rList );
751 r->characters( testParagraph );
752 // writeParagraph( r , testParagraph );
754 r->ignorableWhitespace( L"");
755 r->endElement( L"huhu" );
758 for( i2 = 14 ; i2 >= 0 ; i2-- )
760 r->ignorableWhitespace( L"");
761 r->endElement( UString( L"tag" ) + UString::valueOf( i2 ) );
764 r->endDocument();
766 osl_getSystemTime( &aEndTime );
768 double fStart = (double)aStartTime.Seconds + ((double)aStartTime.Nanosec / 1000000000.0);
769 double fEnd = (double)aEndTime.Seconds + ((double)aEndTime.Nanosec / 1000000000.0);
771 printf( "Performance writing : %g s\n" , fEnd - fStart );