merged tag LIBREOFFICE_3_2_99_3
[LibreOffice.git] / extensions / test / sax / testwriter.cxx
blob692dcb1647ad123ce110f2756ef74c98dc08927f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 // MARKER(update_precomp.py): autogen include statement, do not remove
30 #include "precompiled_extensions.hxx"
32 #include <vector>
33 #include <smart/com/sun/star/test/XSimpleTest.hxx>
34 #include <smart/com/sun/star/lang/XMultiServiceFactory.hxx> // for the multiservice-factories
36 #include <stdio.h>
38 #include <smart/com/sun/star/io/XActiveDataSource.hxx>
39 #include <smart/com/sun/star/io/XOutputStream.hxx>
40 #include <smart/com/sun/star/xml/sax/SAXParseException.hxx>
41 #include <smart/com/sun/star/xml/sax/XParser.hxx>
42 #include <smart/com/sun/star/xml/sax/XExtendedDocumentHandler.hxx>
44 #include <rtl/wstring.hxx>
45 #include <osl/time.h>
46 #include <usr/weak.hxx>
47 #include <tools/string.hxx>
49 #include <usr/factoryhlp.hxx>
51 #include <usr/reflserv.hxx> // for EXTERN_SERVICE_CALLTYPE
53 using namespace std;
54 using namespace rtl;
55 using namespace usr;
57 #define BUILD_ERROR(expr, Message)\
59 m_seqErrors.realloc( m_seqErrors.getLen() + 1 ); \
60 m_seqExceptions.realloc( m_seqExceptions.getLen() + 1 ); \
61 String str; \
62 str += __FILE__;\
63 str += " "; \
64 str += "(" ; \
65 str += __LINE__ ;\
66 str += ")\n";\
67 str += "[ " ; \
68 str += #expr; \
69 str += " ] : " ; \
70 str += Message; \
71 m_seqErrors.getArray()[ m_seqErrors.getLen()-1] = StringToUString( str , CHARSET_SYSTEM ); \
73 ((void)0)
76 #define WARNING_ASSERT(expr, Message) \
77 if( ! (expr) ) { \
78 m_seqWarnings.realloc( m_seqErrors.getLen() +1 ); \
79 String str;\
80 str += __FILE__;\
81 str += " "; \
82 str += "(" ; \
83 str += __LINE__ ;\
84 str += ")\n";\
85 str += "[ " ; \
86 str += #expr; \
87 str += " ] : " ; \
88 str += Message; \
89 m_seqWarnings.getArray()[ m_seqWarnings.getLen()-1] = StringToUString( str , CHARSET_SYSTEM ); \
90 return; \
92 ((void)0)
94 #define ERROR_ASSERT(expr, Message) \
95 if( ! (expr) ) { \
96 BUILD_ERROR(expr, Message );\
97 return; \
99 ((void)0)
101 #define ERROR_EXCEPTION_ASSERT(expr, Message, Exception) \
102 if( !(expr)) { \
103 BUILD_ERROR(expr,Message);\
104 m_seqExceptions.getArray()[ m_seqExceptions.getLen()-1] = UsrAny( Exception );\
105 return; \
107 ((void)0)
109 /****
110 * test szenarios :
114 ****/
117 class OFileWriter :
118 public XOutputStream,
119 public OWeakObject
121 public:
122 OFileWriter( char *pcFile ) { strcpy( m_pcFile , pcFile ); m_f = 0; }
125 public: // refcounting
126 BOOL queryInterface( Uik aUik, XInterfaceRef & rOut )
128 if( XOutputStream::getSmartUik() == aUik ) {
129 rOut = (XOutputStream *) this;
131 else return OWeakObject::queryInterface( aUik , rOut );
133 return TRUE;
135 void acquire() { OWeakObject::acquire(); }
136 void release() { OWeakObject::release(); }
137 void* getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }
139 public:
140 virtual void writeBytes(const Sequence< BYTE >& aData)
141 THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) );
142 virtual void flush(void)
143 THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) );
144 virtual void closeOutput(void)
145 THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) );
148 private:
149 char m_pcFile[256];
150 FILE *m_f;
154 void OFileWriter::writeBytes(const Sequence< BYTE >& aData)
155 THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) )
157 if( ! m_f ) {
158 m_f = fopen( m_pcFile , "w" );
161 fwrite( aData.getConstArray() , 1 , aData.getLen() , m_f );
166 void OFileWriter::flush(void)
167 THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) )
169 fflush( m_f );
172 void OFileWriter::closeOutput(void)
173 THROWS( (NotConnectedException, BufferSizeExceededException, UsrSystemException) )
175 fclose( m_f );
176 m_f = 0;
180 class OSaxWriterTest :
181 public XSimpleTest,
182 public OWeakObject
184 public:
185 OSaxWriterTest( const XMultiServiceFactoryRef & rFactory ) : m_rFactory( rFactory )
189 ~OSaxWriterTest() {}
191 public: // refcounting
192 BOOL queryInterface( Uik aUik, XInterfaceRef & rOut );
193 void acquire() { OWeakObject::acquire(); }
194 void release() { OWeakObject::release(); }
195 void* getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }
197 public:
198 virtual void testInvariant(const UString& TestName, const XInterfaceRef& TestObject)
199 THROWS( ( IllegalArgumentException,
200 UsrSystemException) );
202 virtual INT32 test( const UString& TestName,
203 const XInterfaceRef& TestObject,
204 INT32 hTestHandle) THROWS( ( IllegalArgumentException,
205 UsrSystemException) );
207 virtual BOOL testPassed(void) THROWS( ( UsrSystemException) );
208 virtual Sequence< UString > getErrors(void) THROWS( (UsrSystemException) );
209 virtual Sequence< UsrAny > getErrorExceptions(void) THROWS( (UsrSystemException) );
210 virtual Sequence< UString > getWarnings(void) THROWS( (UsrSystemException) );
212 private:
213 void testSimple( const XExtendedDocumentHandlerRef &r );
214 void testExceptions( const XExtendedDocumentHandlerRef &r );
215 void testDTD( const XExtendedDocumentHandlerRef &r );
216 void testPerformance( const XExtendedDocumentHandlerRef &r );
217 void writeParagraph( const XExtendedDocumentHandlerRef &r , const UString & s);
219 private:
220 Sequence<UsrAny> m_seqExceptions;
221 Sequence<UString> m_seqErrors;
222 Sequence<UString> m_seqWarnings;
223 XMultiServiceFactoryRef m_rFactory;
229 /*----------------------------------------
231 * Attributlist implementation
233 *----------------------------------------*/
234 struct AttributeListImpl_impl;
235 class AttributeListImpl :
236 public XAttributeList,
237 public OWeakObject
239 public:
240 AttributeListImpl();
241 AttributeListImpl( const AttributeListImpl & );
242 ~AttributeListImpl();
244 public:
245 BOOL queryInterface( Uik aUik, XInterfaceRef & rOut );
246 void acquire() { OWeakObject::acquire(); }
247 void release() { OWeakObject::release(); }
248 void* getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }
250 public:
251 virtual INT16 getLength(void) THROWS( (UsrSystemException) );
252 virtual UString getNameByIndex(INT16 i) THROWS( (UsrSystemException) );
253 virtual UString getTypeByIndex(INT16 i) THROWS( (UsrSystemException) );
254 virtual UString getTypeByName(const UString& aName) THROWS( (UsrSystemException) );
255 virtual UString getValueByIndex(INT16 i) THROWS( (UsrSystemException) );
256 virtual UString getValueByName(const UString& aName) THROWS( (UsrSystemException) );
258 public:
259 void addAttribute( const UString &sName , const UString &sType , const UString &sValue );
260 void clear();
262 private:
263 struct AttributeListImpl_impl *m_pImpl;
267 struct TagAttribute
269 TagAttribute(){}
270 TagAttribute( const UString &sName, const UString &sType , const UString &sValue )
272 this->sName = sName;
273 this->sType = sType;
274 this->sValue = sValue;
277 UString sName;
278 UString sType;
279 UString sValue;
282 struct AttributeListImpl_impl
284 AttributeListImpl_impl()
286 // performance improvement during adding
287 vecAttribute.reserve(20);
289 vector<struct TagAttribute> vecAttribute;
294 INT16 AttributeListImpl::getLength(void) THROWS( (UsrSystemException) )
296 return m_pImpl->vecAttribute.size();
300 AttributeListImpl::AttributeListImpl( const AttributeListImpl &r )
302 m_pImpl = new AttributeListImpl_impl;
303 *m_pImpl = *(r.m_pImpl);
306 UString AttributeListImpl::getNameByIndex(INT16 i) THROWS( (UsrSystemException) )
308 if( i < m_pImpl->vecAttribute.size() ) {
309 return m_pImpl->vecAttribute[i].sName;
311 return UString();
315 UString AttributeListImpl::getTypeByIndex(INT16 i) THROWS( (UsrSystemException) )
317 if( i < m_pImpl->vecAttribute.size() ) {
318 return m_pImpl->vecAttribute[i].sType;
320 return UString();
323 UString AttributeListImpl::getValueByIndex(INT16 i) THROWS( (UsrSystemException) )
325 if( i < m_pImpl->vecAttribute.size() ) {
326 return m_pImpl->vecAttribute[i].sValue;
328 return UString();
332 UString AttributeListImpl::getTypeByName( const UString& sName ) THROWS( (UsrSystemException) )
334 vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
336 for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
337 if( (*ii).sName == sName ) {
338 return (*ii).sType;
341 return UString();
344 UString AttributeListImpl::getValueByName(const UString& sName) THROWS( (UsrSystemException) )
346 vector<struct TagAttribute>::iterator ii = m_pImpl->vecAttribute.begin();
348 for( ; ii != m_pImpl->vecAttribute.end() ; ii ++ ) {
349 if( (*ii).sName == sName ) {
350 return (*ii).sValue;
353 return UString();
357 BOOL AttributeListImpl::queryInterface( Uik aUik, XInterfaceRef & rOut )
359 if( aUik == XAttributeList::getSmartUik() ) {
360 rOut = (XAttributeList * )this;
362 else {
363 return OWeakObject::queryInterface( aUik , rOut );
365 return TRUE;
369 AttributeListImpl::AttributeListImpl()
371 m_pImpl = new AttributeListImpl_impl;
376 AttributeListImpl::~AttributeListImpl()
378 delete m_pImpl;
382 void AttributeListImpl::addAttribute( const UString &sName ,
383 const UString &sType ,
384 const UString &sValue )
386 m_pImpl->vecAttribute.push_back( TagAttribute( sName , sType , sValue ) );
389 void AttributeListImpl::clear()
391 vector<struct TagAttribute> dummy;
392 m_pImpl->vecAttribute.swap( dummy );
394 OSL_ASSERT( ! getLength() );
408 * for external binding
412 XInterfaceRef OSaxWriterTest_CreateInstance( const XMultiServiceFactoryRef & rSMgr ) THROWS((Exception))
414 OSaxWriterTest *p = new OSaxWriterTest( rSMgr );
415 XInterfaceRef xService = *p;
416 return xService;
419 UString OSaxWriterTest_getServiceName( ) THROWS( () )
421 return L"test.com.sun.star.xml.sax.Writer";
424 UString OSaxWriterTest_getImplementationName( ) THROWS( () )
426 return L"test.extensions.xml.sax.Writer";
429 Sequence<UString> OSaxWriterTest_getSupportedServiceNames( ) THROWS( () )
431 Sequence<UString> aRet(1);
433 aRet.getArray()[0] = OSaxWriterTest_getImplementationName( );
435 return aRet;
439 BOOL OSaxWriterTest::queryInterface( Uik uik , XInterfaceRef &rOut )
441 if( XSimpleTest::getSmartUik() == uik ) {
442 rOut = (XSimpleTest *) this;
444 else {
445 return OWeakObject::queryInterface( uik , rOut );
447 return TRUE;
451 void OSaxWriterTest::testInvariant( const UString& TestName, const XInterfaceRef& TestObject )
452 THROWS( ( IllegalArgumentException,
453 UsrSystemException) )
455 if( L"com.sun.star.xml.sax.Writer" == TestName ) {
456 XDocumentHandlerRef doc( TestObject , USR_QUERY );
457 XExtendedDocumentHandlerRef ext( TestObject , USR_QUERY );
458 XActiveDataSourceRef source( TestObject , USR_QUERY );
460 ERROR_ASSERT( doc.is() , "XDocumentHandler cannot be queried" );
461 ERROR_ASSERT( ext.is() , "XExtendedDocumentHandler cannot be queried" );
462 ERROR_ASSERT( source.is() , "XActiveDataSource cannot be queried" );
464 else {
465 BUILD_ERROR( 0 , "wrong test" );
470 INT32 OSaxWriterTest::test( const UString& TestName,
471 const XInterfaceRef& TestObject,
472 INT32 hTestHandle) THROWS( ( IllegalArgumentException,
473 UsrSystemException) )
475 if( L"com.sun.star.xml.sax.Writer" == TestName ) {
476 try {
477 if( 0 == hTestHandle ) {
478 testInvariant( TestName , TestObject );
480 else {
482 XExtendedDocumentHandlerRef writer( TestObject , USR_QUERY );
484 if( 1 == hTestHandle ) {
485 testSimple( writer );
487 else if( 2 == hTestHandle ) {
488 testExceptions( writer );
490 else if( 3 == hTestHandle ) {
491 testDTD( writer );
493 else if( 4 == hTestHandle ) {
494 testPerformance( writer );
498 catch( Exception& e ) {
499 BUILD_ERROR( 0 , UStringToString( e.getName() , CHARSET_SYSTEM ).GetCharStr() );
501 catch(...) {
502 BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" );
505 hTestHandle ++;
507 if( hTestHandle >= 5) {
508 // all tests finished.
509 hTestHandle = -1;
512 else {
513 BUILD_ERROR( 0 , "service not supported by test." );
515 return hTestHandle;
520 BOOL OSaxWriterTest::testPassed(void) THROWS( (UsrSystemException) )
522 return m_seqErrors.getLen() == 0;
526 Sequence< UString > OSaxWriterTest::getErrors(void) THROWS( (UsrSystemException) )
528 return m_seqErrors;
532 Sequence< UsrAny > OSaxWriterTest::getErrorExceptions(void) THROWS( (UsrSystemException) )
534 return m_seqExceptions;
538 Sequence< UString > OSaxWriterTest::getWarnings(void) THROWS( (UsrSystemException) )
540 return m_seqWarnings;
543 void OSaxWriterTest::writeParagraph( const XExtendedDocumentHandlerRef &r , const UString & s)
545 int nMax = s.len();
546 int nStart = 0;
548 Sequence<UINT16> seq( s.len() );
549 memcpy( seq.getArray() , s.getStr() , s.len() * sizeof( UINT16 ) );
551 for( int n = 1 ; n < nMax ; n++ ){
552 if( 32 == seq.getArray()[n] ) {
553 r->allowLineBreak();
554 r->characters( s.copy( nStart , n - nStart ) );
555 nStart = n;
558 r->allowLineBreak();
559 r->characters( s.copy( nStart , n - nStart ) );
566 void OSaxWriterTest::testSimple( const XExtendedDocumentHandlerRef &r )
568 UString testParagraph = L"Dies ist ein bloeder Test um zu uberpruefen, ob der SAXWriter "
569 L"wohl Zeilenumbrueche halbwegs richtig macht oder ob er die Zeile "
570 L"bis zum bitteren Ende schreibt.";
572 OFileWriter *pw = new OFileWriter("output.xml");
573 AttributeListImpl *pList = new AttributeListImpl;
575 XAttributeListRef rList( (XAttributeList *) pList , USR_QUERY );
576 XOutputStreamRef ref( ( XOutputStream * ) pw , USR_QUERY );
578 XActiveDataSourceRef source( r , USR_QUERY );
580 ERROR_ASSERT( ref.is() , "no output stream" );
581 ERROR_ASSERT( source.is() , "no active data source" );
583 source->setOutputStream( ref );
585 r->startDocument();
587 pList->addAttribute( L"Arg1" , L"CDATA" , L"bla\n u" );
588 pList->addAttribute( L"Arg2" , L"CDATA" , L"blub" );
590 r->startElement( L"tag1" , rList );
591 r->ignorableWhitespace( L"" );
593 r->characters( L"huhu" );
594 r->ignorableWhitespace( L"" );
596 r->startElement( L"hi" , rList );
597 r->ignorableWhitespace( L"" );
599 // the enpassant must be converted & -> &amp;
600 r->characters( L"&#252;" );
602 // Test added for mib. Tests if errors during conversions occurs
603 r->ignorableWhitespace( UString() );
604 sal_Char array[256];
605 for( sal_Int32 n = 32 ; n < 254 ; n ++ ) {
606 array[n-32] = n;
608 array[254-32] = 0;
609 r->characters(
610 StringToUString( array , RTL_TEXTENCODING_SYMBOL )
612 r->ignorableWhitespace( UString() );
614 // '>' must not be converted
615 r->startCDATA();
616 r->characters( L">fsfsdf<" );
617 r->endCDATA();
618 r->ignorableWhitespace( UString() );
620 writeParagraph( r , testParagraph );
623 r->ignorableWhitespace( UString() );
624 r->comment( L"Dies ist ein Kommentar !" );
625 r->ignorableWhitespace( UString() );
627 r->startElement( L"emptytagtest" , rList );
628 r->endElement( L"emptytagtest" );
630 r->endElement( L"hi" );
631 r->ignorableWhitespace( L"" );
633 r->endElement( L"tag1" );
634 r->endDocument();
638 void OSaxWriterTest::testExceptions( const XExtendedDocumentHandlerRef & r )
641 OFileWriter *pw = new OFileWriter("output2.xml");
642 AttributeListImpl *pList = new AttributeListImpl;
644 XAttributeListRef rList( (XAttributeList *) pList , USR_QUERY );
645 XOutputStreamRef ref( ( XOutputStream * ) pw , USR_QUERY );
647 XActiveDataSourceRef source( r , USR_QUERY );
649 ERROR_ASSERT( ref.is() , "no output stream" );
650 ERROR_ASSERT( source.is() , "no active data source" );
652 source->setOutputStream( ref );
654 { // startDocument must be called before start element
655 BOOL bException = TRUE;
656 try {
657 r->startElement( L"huhu" , rList );
658 bException = FALSE;
660 catch( SAXException& e ) {
663 ERROR_ASSERT( bException , "expected exception not thrown !" );
666 r->startDocument();
668 r->startElement( L"huhu" , rList );
669 r->startCDATA();
672 BOOL bException = TRUE;
673 try {
674 r->startElement( L"huhu" , rList );
675 bException = FALSE;
677 catch( SAXException& e ) {
680 ERROR_ASSERT( bException , "expected exception not thrown !" );
683 r->endCDATA();
684 r->endElement( L"hi" );
686 r->endDocument();
690 void OSaxWriterTest::testDTD(const XExtendedDocumentHandlerRef &r )
692 OFileWriter *pw = new OFileWriter("outputDTD.xml");
693 AttributeListImpl *pList = new AttributeListImpl;
695 XAttributeListRef rList( (XAttributeList *) pList , USR_QUERY );
696 XOutputStreamRef ref( ( XOutputStream * ) pw , USR_QUERY );
698 XActiveDataSourceRef source( r , USR_QUERY );
700 ERROR_ASSERT( ref.is() , "no output stream" );
701 ERROR_ASSERT( source.is() , "no active data source" );
703 source->setOutputStream( ref );
706 r->startDocument();
707 r->unknown( L"<!DOCTYPE iCalendar >\n" );
708 r->startElement( L"huhu" , rList );
710 r->endElement( L"huhu" );
711 r->endDocument();
714 void OSaxWriterTest::testPerformance(const XExtendedDocumentHandlerRef &r )
716 OFileWriter *pw = new OFileWriter("testPerformance.xml");
717 AttributeListImpl *pList = new AttributeListImpl;
719 UString testParagraph = L"Dies ist ein bloeder Test um zu uberpruefen, ob der SAXWriter "
720 L"wohl > Zeilenumbrueche halbwegs richtig macht oder ob er die Zeile "
721 L"bis zum bitteren Ende schreibt.";
724 XAttributeListRef rList( (XAttributeList *) pList , USR_QUERY );
725 XOutputStreamRef ref( ( XOutputStream * ) pw , USR_QUERY );
727 XActiveDataSourceRef source( r , USR_QUERY );
729 ERROR_ASSERT( ref.is() , "no output stream" );
730 ERROR_ASSERT( source.is() , "no active data source" );
732 source->setOutputStream( ref );
734 TimeValue aStartTime, aEndTime;
735 osl_getSystemTime( &aStartTime );
738 r->startDocument();
739 // just write a bunch of xml tags !
740 // for performance testing
741 sal_Int32 i2;
742 for( i2 = 0 ; i2 < 15 ; i2 ++ )
744 r->startElement( UString( L"tag" ) + UString::valueOf( i2 ), rList );
745 for( sal_Int32 i = 0 ; i < 450 ; i ++ )
747 r->ignorableWhitespace( L"");
748 r->startElement( L"huhu" , rList );
749 r->characters( testParagraph );
750 // writeParagraph( r , testParagraph );
752 r->ignorableWhitespace( L"");
753 r->endElement( L"huhu" );
756 for( i2 = 14 ; i2 >= 0 ; i2-- )
758 r->ignorableWhitespace( L"");
759 r->endElement( UString( L"tag" ) + UString::valueOf( i2 ) );
762 r->endDocument();
764 osl_getSystemTime( &aEndTime );
766 double fStart = (double)aStartTime.Seconds + ((double)aStartTime.Nanosec / 1000000000.0);
767 double fEnd = (double)aEndTime.Seconds + ((double)aEndTime.Nanosec / 1000000000.0);
769 printf( "Performance writing : %g s\n" , fEnd - fStart );
772 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */