/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_io.hxx" #include #include #include #include #include #include #include #include // OWeakObject #include #include #include #include using namespace ::rtl; using namespace ::osl; using namespace ::cppu; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::io; using namespace ::com::sun::star::lang; using namespace ::com::sun::star::test; // streams #include "testfactreg.hxx" #define IMPLEMENTATION_NAME "test.com.sun.star.comp.extensions.stm.Pipe" #define SERVICE_NAME "test.com.sun.star.io.Pipe" class WriteToStreamThread : public Thread { public: WriteToStreamThread( Reference< XOutputStream > xOutput , int iMax ) { m_output = xOutput; m_iMax = iMax; } virtual ~WriteToStreamThread() {} protected: /// Working method which should be overridden. virtual void SAL_CALL run() { for( int i = 0 ; i < m_iMax ; i ++ ) { m_output->writeBytes( createIntSeq(i) ); } m_output->closeOutput(); } /** Called when run() is done. * You might want to override it to do some cleanup. */ virtual void SAL_CALL onTerminated() { delete this; } private: Reference < XOutputStream > m_output; int m_iMax; }; class OPipeTest : public WeakImplHelper1 < XSimpleTest > { public: OPipeTest( const Reference< XMultiServiceFactory > & rFactory ); ~OPipeTest(); public: // implementation names static Sequence< OUString > getSupportedServiceNames_Static(void) throw(); static OUString getImplementationName_Static() throw(); public: virtual void SAL_CALL testInvariant(const OUString& TestName, const Reference < XInterface >& TestObject) throw ( IllegalArgumentException, RuntimeException) ; virtual sal_Int32 SAL_CALL test( const OUString& TestName, const Reference < XInterface >& TestObject, sal_Int32 hTestHandle) throw ( IllegalArgumentException, RuntimeException); virtual sal_Bool SAL_CALL testPassed(void) throw ( RuntimeException) ; virtual Sequence< OUString > SAL_CALL getErrors(void) throw (RuntimeException) ; virtual Sequence< Any > SAL_CALL getErrorExceptions(void) throw (RuntimeException); virtual Sequence< OUString > SAL_CALL getWarnings(void) throw (RuntimeException); private: void testSimple( const Reference < XInterface > & ); void testBufferResizing( const Reference < XInterface > & ); void testMultithreading( const Reference < XInterface > & ); private: Sequence m_seqExceptions; Sequence m_seqErrors; Sequence m_seqWarnings; }; OPipeTest::OPipeTest( const Reference< XMultiServiceFactory > &rFactory ) { } OPipeTest::~OPipeTest() { } void OPipeTest::testInvariant( const OUString& TestName, const Reference < XInterface >& TestObject ) throw ( IllegalArgumentException, RuntimeException) { Reference< XServiceInfo > info( TestObject, UNO_QUERY ); ERROR_ASSERT( info.is() , "XServiceInfo not supported !" ); if( info.is() ) { ERROR_ASSERT( info->supportsService( TestName ), "XServiceInfo test failed" ); ERROR_ASSERT( ! info->supportsService( OUString( RTL_CONSTASCII_USTRINGPARAM("bla bluzb") ) ), "XServiceInfo test failed" ); } } sal_Int32 OPipeTest::test( const OUString& TestName, const Reference < XInterface >& TestObject, sal_Int32 hTestHandle) throw ( IllegalArgumentException, RuntimeException) { if( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.io.Pipe") ) == TestName ) { try { if( 0 == hTestHandle ) { testInvariant( TestName , TestObject ); } else if( 1 == hTestHandle ) { testSimple( TestObject ); } else if( 2 == hTestHandle ) { testBufferResizing( TestObject ); } else if( 3 == hTestHandle ) { testMultithreading( TestObject ); } } catch( Exception & e ) { OString s = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ); BUILD_ERROR( 0 , s.getStr() ); } catch( ... ) { BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" ); } hTestHandle ++; if( 4 == hTestHandle ) { // all tests finished. hTestHandle = -1; } } else { throw IllegalArgumentException(); } return hTestHandle; } sal_Bool OPipeTest::testPassed(void) throw (RuntimeException) { return m_seqErrors.getLength() == 0; } Sequence< OUString > OPipeTest::getErrors(void) throw (RuntimeException) { return m_seqErrors; } Sequence< Any > OPipeTest::getErrorExceptions(void) throw (RuntimeException) { return m_seqExceptions; } Sequence< OUString > OPipeTest::getWarnings(void) throw (RuntimeException) { return m_seqWarnings; } /*** * the test methods * ****/ void OPipeTest::testSimple( const Reference < XInterface > &r ) { Reference< XInputStream > input( r , UNO_QUERY ); Reference < XOutputStream > output( r , UNO_QUERY ); ERROR_ASSERT( input.is() , "queryInterface on XInputStream failed" ); ERROR_ASSERT( output.is() , "queryInterface onXOutputStream failed" ); // basic read/write Sequence seqWrite = createSeq( "Hallo, du Ei !" ); Sequence seqRead; for( int i = 0 ; i < 5000 ; i ++ ) { output->writeBytes( seqWrite ); input->readBytes( seqRead , input->available() ); ERROR_ASSERT( ! strcmp( (char *) seqWrite.getArray() , (char * )seqRead.getArray() ) , "error during read/write/skip" ); ERROR_ASSERT( 0 == input->available() , "error during read/write/skip" ); // available shouldn't return a negative value input->skipBytes( seqWrite.getLength() - 5 ); ERROR_ASSERT( 0 == input->available() , "wrong available after skip" ); // 5 bytes should be available output->writeBytes( seqWrite ); ERROR_ASSERT( 5 == input->available() , "wrong available after skip/write " ); input->readBytes( seqRead , 5 ); ERROR_ASSERT( ! strcmp( (char*) seqRead.getArray() , (char*) &( seqWrite.getArray()[seqWrite.getLength()-5] ) ), "write/read mismatich" ); } output->writeBytes( seqWrite ); ERROR_ASSERT( seqWrite.getLength() == input->available(), "wrong available() after write" ); ERROR_ASSERT( 10 == input->readSomeBytes( seqRead , 10 ) , "maximal number of bytes ignored" ); ERROR_ASSERT( seqWrite.getLength() -10 == input->readSomeBytes( seqRead , 100 ) , "something wrong with readSomeBytes" ); output->closeOutput(); try{ output->writeBytes( Sequence (100) ); ERROR_ASSERT( 0 , "writing on a closed stream does not cause an exception" ); } catch (IOException & ) { } ERROR_ASSERT(! input->readBytes( seqRead , 1 ), "eof not found !" ); input->closeInput(); try { input->readBytes( seqRead , 1 ); ERROR_ASSERT( 0 , "reading from a closed stream does not cause an exception" ); } catch( IOException & ) { } try { input->available( ); ERROR_ASSERT( 0 , "calling available from a closed stream should thrown an io exception" ); } catch( IOException & ) { } try { input->skipBytes(42 ); ERROR_ASSERT( 0 , "calling available from a closed stream should thrown an io exception" ); } catch( IOException & ) { } } void OPipeTest::testBufferResizing( const Reference < XInterface > &r ) { int i; int iMax = 20000; Reference< XInputStream > input( r , UNO_QUERY ); Reference < XOutputStream > output( r , UNO_QUERY ); ERROR_ASSERT( input.is() , "queryInterface on XInputStream failed" ); ERROR_ASSERT( output.is() , "queryInterface on XOutputStream failed" ); Sequence seqRead; // this is just to better check the // internal buffers output->writeBytes( Sequence(100) ); Sequence< sal_Int8 > dummy; input->readBytes( dummy , 100); for( i = 0 ; i < iMax ; i ++ ) { output->writeBytes( createIntSeq( i ) ); } for( i = 0 ; i < iMax ; i ++ ) { input->readBytes( seqRead, createIntSeq(i).getLength() ); ERROR_ASSERT( ! strcmp( (char*) seqRead.getArray() , (char*) createIntSeq(i).getArray() ) , "written/read mismatch\n" ); } output->closeOutput(); ERROR_ASSERT( ! input->readBytes( seqRead , 1 ) , "eof not reached !" ); input->closeInput(); } void OPipeTest::testMultithreading( const Reference < XInterface > &r ) { int i; int iMax = 30000; Reference< XInputStream > input( r , UNO_QUERY ); Reference < XOutputStream > output( r , UNO_QUERY ); ERROR_ASSERT( input.is() , "queryInterface on XInputStream failed" ); ERROR_ASSERT( output.is() , "queryInterface on XOutputStream failed" ); Sequence seqRead; // deletes itself Thread *p = new WriteToStreamThread( output, iMax ); ERROR_ASSERT( p , "couldn't create thread for testing !\n" ); p->create(); for( i = 0 ; sal_True ; i ++ ) { if( 0 == input->readBytes( seqRead, createIntSeq(i).getLength() ) ) { // eof reached ! break; } ERROR_ASSERT( ! strcmp( (char*) seqRead.getArray() , (char*) createIntSeq(i).getArray() ) , "written/read mismatch\n" ); } ERROR_ASSERT( i == iMax , "less elements read than written !"); input->closeInput(); } /** * for external binding * * **/ Reference < XInterface > SAL_CALL OPipeTest_CreateInstance( const Reference< XMultiServiceFactory> & rSMgr ) throw (Exception) { OPipeTest *p = new OPipeTest( rSMgr ); Reference< XInterface > x ( SAL_STATIC_CAST( OWeakObject * , p ) ); return x; } Sequence OPipeTest_getSupportedServiceNames(void) throw() { Sequence aRet(1); aRet.getArray()[0] = OPipeTest_getServiceName(); return aRet; } OUString OPipeTest_getServiceName() throw() { return OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICE_NAME ) ); } OUString OPipeTest_getImplementationName() throw() { return OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) ); }