1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 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. 14 * 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). 20 * 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. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_io.hxx" 30 31 #include <com/sun/star/test/XSimpleTest.hpp> 32 #include <com/sun/star/io/XInputStream.hpp> 33 #include <com/sun/star/io/XOutputStream.hpp> 34 #include <com/sun/star/io/XConnectable.hpp> 35 #include <com/sun/star/lang/IllegalArgumentException.hpp> 36 37 #include <com/sun/star/lang/XServiceInfo.hpp> 38 39 #include <cppuhelper/factory.hxx> 40 41 #include <cppuhelper/implbase1.hxx> // OWeakObject 42 43 #include <osl/conditn.hxx> 44 #include <osl/mutex.hxx> 45 #include <osl/thread.hxx> 46 47 #include <string.h> 48 49 using namespace ::rtl; 50 using namespace ::osl; 51 using namespace ::cppu; 52 using namespace ::com::sun::star::uno; 53 using namespace ::com::sun::star::io; 54 using namespace ::com::sun::star::lang; 55 using namespace ::com::sun::star::test; 56 // streams 57 58 #include "testfactreg.hxx" 59 #define IMPLEMENTATION_NAME "test.com.sun.star.comp.extensions.stm.Pipe" 60 #define SERVICE_NAME "test.com.sun.star.io.Pipe" 61 62 63 class WriteToStreamThread : 64 public Thread 65 { 66 67 public: 68 69 WriteToStreamThread( Reference< XOutputStream > xOutput , int iMax ) 70 { 71 m_output = xOutput; 72 m_iMax = iMax; 73 } 74 75 virtual ~WriteToStreamThread() {} 76 77 78 protected: 79 80 /// Working method which should be overridden. 81 virtual void SAL_CALL run() { 82 for( int i = 0 ; i < m_iMax ; i ++ ) { 83 m_output->writeBytes( createIntSeq(i) ); 84 } 85 m_output->closeOutput(); 86 } 87 88 /** Called when run() is done. 89 * You might want to override it to do some cleanup. 90 */ 91 virtual void SAL_CALL onTerminated() 92 { 93 delete this; 94 } 95 96 97 private: 98 99 Reference < XOutputStream > m_output; 100 int m_iMax; 101 }; 102 103 104 105 class OPipeTest : public WeakImplHelper1 < XSimpleTest > 106 { 107 public: 108 OPipeTest( const Reference< XMultiServiceFactory > & rFactory ); 109 ~OPipeTest(); 110 111 public: // implementation names 112 static Sequence< OUString > getSupportedServiceNames_Static(void) throw(); 113 static OUString getImplementationName_Static() throw(); 114 115 public: 116 virtual void SAL_CALL testInvariant(const OUString& TestName, const Reference < XInterface >& TestObject) 117 throw ( IllegalArgumentException, RuntimeException) ; 118 119 virtual sal_Int32 SAL_CALL test( const OUString& TestName, 120 const Reference < XInterface >& TestObject, 121 sal_Int32 hTestHandle) 122 throw ( IllegalArgumentException, 123 RuntimeException); 124 125 virtual sal_Bool SAL_CALL testPassed(void) throw ( RuntimeException) ; 126 virtual Sequence< OUString > SAL_CALL getErrors(void) throw (RuntimeException) ; 127 virtual Sequence< Any > SAL_CALL getErrorExceptions(void) throw (RuntimeException); 128 virtual Sequence< OUString > SAL_CALL getWarnings(void) throw (RuntimeException); 129 130 private: 131 void testSimple( const Reference < XInterface > & ); 132 void testBufferResizing( const Reference < XInterface > & ); 133 void testMultithreading( const Reference < XInterface > & ); 134 135 private: 136 Sequence<Any> m_seqExceptions; 137 Sequence<OUString> m_seqErrors; 138 Sequence<OUString> m_seqWarnings; 139 140 }; 141 142 143 144 OPipeTest::OPipeTest( const Reference< XMultiServiceFactory > &rFactory ) 145 { 146 147 } 148 149 OPipeTest::~OPipeTest() 150 { 151 152 } 153 154 155 156 void OPipeTest::testInvariant( const OUString& TestName, const Reference < XInterface >& TestObject ) 157 throw ( IllegalArgumentException, 158 RuntimeException) 159 { 160 Reference< XServiceInfo > info( TestObject, UNO_QUERY ); 161 ERROR_ASSERT( info.is() , "XServiceInfo not supported !" ); 162 if( info.is() ) 163 { 164 ERROR_ASSERT( info->supportsService( TestName ), "XServiceInfo test failed" ); 165 ERROR_ASSERT( ! info->supportsService( 166 OUString( RTL_CONSTASCII_USTRINGPARAM("bla bluzb") ) ), "XServiceInfo test failed" ); 167 } 168 169 } 170 171 172 sal_Int32 OPipeTest::test( 173 const OUString& TestName, 174 const Reference < XInterface >& TestObject, 175 sal_Int32 hTestHandle) 176 throw ( IllegalArgumentException, RuntimeException) 177 { 178 if( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.io.Pipe") ) == TestName ) { 179 try 180 { 181 if( 0 == hTestHandle ) { 182 testInvariant( TestName , TestObject ); 183 } 184 else if( 1 == hTestHandle ) { 185 testSimple( TestObject ); 186 } 187 else if( 2 == hTestHandle ) { 188 testBufferResizing( TestObject ); 189 } 190 else if( 3 == hTestHandle ) { 191 testMultithreading( TestObject ); 192 } 193 } 194 catch( Exception & e ) 195 { 196 OString s = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ); 197 BUILD_ERROR( 0 , s.getStr() ); 198 } 199 catch( ... ) 200 { 201 BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" ); 202 } 203 204 hTestHandle ++; 205 206 if( 4 == hTestHandle ) 207 { 208 // all tests finished. 209 hTestHandle = -1; 210 } 211 } 212 else { 213 throw IllegalArgumentException(); 214 } 215 return hTestHandle; 216 } 217 218 219 220 sal_Bool OPipeTest::testPassed(void) throw (RuntimeException) 221 { 222 return m_seqErrors.getLength() == 0; 223 } 224 225 226 Sequence< OUString > OPipeTest::getErrors(void) throw (RuntimeException) 227 { 228 return m_seqErrors; 229 } 230 231 232 Sequence< Any > OPipeTest::getErrorExceptions(void) throw (RuntimeException) 233 { 234 return m_seqExceptions; 235 } 236 237 238 Sequence< OUString > OPipeTest::getWarnings(void) throw (RuntimeException) 239 { 240 return m_seqWarnings; 241 } 242 243 244 /*** 245 * the test methods 246 * 247 ****/ 248 249 250 void OPipeTest::testSimple( const Reference < XInterface > &r ) 251 { 252 253 Reference< XInputStream > input( r , UNO_QUERY ); 254 Reference < XOutputStream > output( r , UNO_QUERY ); 255 256 ERROR_ASSERT( input.is() , "queryInterface on XInputStream failed" ); 257 ERROR_ASSERT( output.is() , "queryInterface onXOutputStream failed" ); 258 259 // basic read/write 260 Sequence<sal_Int8> seqWrite = createSeq( "Hallo, du Ei !" ); 261 262 Sequence<sal_Int8> seqRead; 263 for( int i = 0 ; i < 5000 ; i ++ ) { 264 output->writeBytes( seqWrite ); 265 input->readBytes( seqRead , input->available() ); 266 267 ERROR_ASSERT( ! strcmp( (char *) seqWrite.getArray() , (char * )seqRead.getArray() ) , 268 "error during read/write/skip" ); 269 ERROR_ASSERT( 0 == input->available() , 270 "error during read/write/skip" ); 271 272 // available shouldn't return a negative value 273 input->skipBytes( seqWrite.getLength() - 5 ); 274 ERROR_ASSERT( 0 == input->available() , "wrong available after skip" ); 275 276 // 5 bytes should be available 277 output->writeBytes( seqWrite ); 278 ERROR_ASSERT( 5 == input->available() , "wrong available after skip/write " ); 279 280 input->readBytes( seqRead , 5 ); 281 ERROR_ASSERT( ! strcmp( (char*) seqRead.getArray() , 282 (char*) &( seqWrite.getArray()[seqWrite.getLength()-5] ) ), 283 "write/read mismatich" ); 284 285 } 286 287 output->writeBytes( seqWrite ); 288 ERROR_ASSERT( seqWrite.getLength() == input->available(), "wrong available() after write" ); 289 290 ERROR_ASSERT( 10 == input->readSomeBytes( seqRead , 10 ) , "maximal number of bytes ignored" ); 291 ERROR_ASSERT( seqWrite.getLength() -10 == input->readSomeBytes( seqRead , 100 ) , 292 "something wrong with readSomeBytes" ); 293 294 295 output->closeOutput(); 296 try{ 297 output->writeBytes( Sequence<sal_Int8> (100) ); 298 ERROR_ASSERT( 0 , "writing on a closed stream does not cause an exception" ); 299 } 300 catch (IOException & ) 301 { 302 } 303 304 ERROR_ASSERT(! input->readBytes( seqRead , 1 ), "eof not found !" ); 305 306 input->closeInput(); 307 try 308 { 309 input->readBytes( seqRead , 1 ); 310 ERROR_ASSERT( 0 , "reading from a closed stream does not cause an exception" ); 311 } 312 catch( IOException & ) { 313 } 314 315 try 316 { 317 input->available( ); 318 ERROR_ASSERT( 0 , "calling available from a closed stream should thrown an io exception" ); 319 } 320 catch( IOException & ) 321 { 322 323 } 324 try 325 { 326 input->skipBytes(42 ); 327 ERROR_ASSERT( 0 , "calling available from a closed stream should thrown an io exception" ); 328 } 329 catch( IOException & ) 330 { 331 332 } 333 } 334 335 void OPipeTest::testBufferResizing( const Reference < XInterface > &r ) 336 { 337 int i; 338 int iMax = 20000; 339 Reference< XInputStream > input( r , UNO_QUERY ); 340 Reference < XOutputStream > output( r , UNO_QUERY ); 341 342 ERROR_ASSERT( input.is() , "queryInterface on XInputStream failed" ); 343 ERROR_ASSERT( output.is() , "queryInterface on XOutputStream failed" ); 344 345 Sequence<sal_Int8> seqRead; 346 347 // this is just to better check the 348 // internal buffers 349 output->writeBytes( Sequence<sal_Int8>(100) ); 350 Sequence< sal_Int8 > dummy; 351 input->readBytes( dummy , 100); 352 353 for( i = 0 ; i < iMax ; i ++ ) { 354 output->writeBytes( createIntSeq( i ) ); 355 } 356 357 for( i = 0 ; i < iMax ; i ++ ) { 358 input->readBytes( seqRead, createIntSeq(i).getLength() ); 359 ERROR_ASSERT( ! strcmp( (char*) seqRead.getArray() , 360 (char*) createIntSeq(i).getArray() ) , 361 "written/read mismatch\n" ); 362 } 363 364 output->closeOutput(); 365 ERROR_ASSERT( ! input->readBytes( seqRead , 1 ) , "eof not reached !" ); 366 input->closeInput(); 367 } 368 369 370 371 void OPipeTest::testMultithreading( const Reference < XInterface > &r ) 372 { 373 374 int i; 375 int iMax = 30000; 376 377 Reference< XInputStream > input( r , UNO_QUERY ); 378 Reference < XOutputStream > output( r , UNO_QUERY ); 379 380 ERROR_ASSERT( input.is() , "queryInterface on XInputStream failed" ); 381 ERROR_ASSERT( output.is() , "queryInterface on XOutputStream failed" ); 382 383 Sequence<sal_Int8> seqRead; 384 385 // deletes itself 386 Thread *p = new WriteToStreamThread( output, iMax ); 387 388 ERROR_ASSERT( p , "couldn't create thread for testing !\n" ); 389 390 p->create(); 391 392 for( i = 0 ; sal_True ; i ++ ) { 393 if( 0 == input->readBytes( seqRead, createIntSeq(i).getLength() ) ) { 394 // eof reached ! 395 break; 396 } 397 398 ERROR_ASSERT( ! strcmp( (char*) seqRead.getArray() , 399 (char*) createIntSeq(i).getArray() ) , 400 "written/read mismatch\n" ); 401 } 402 403 ERROR_ASSERT( i == iMax , "less elements read than written !"); 404 input->closeInput(); 405 } 406 407 408 409 /** 410 * for external binding 411 * 412 * 413 **/ 414 Reference < XInterface > SAL_CALL OPipeTest_CreateInstance( const Reference< XMultiServiceFactory> & rSMgr ) throw (Exception) 415 { 416 OPipeTest *p = new OPipeTest( rSMgr ); 417 Reference< XInterface > x ( SAL_STATIC_CAST( OWeakObject * , p ) ); 418 return x; 419 } 420 421 422 423 Sequence<OUString> OPipeTest_getSupportedServiceNames(void) throw() 424 { 425 Sequence<OUString> aRet(1); 426 aRet.getArray()[0] = OPipeTest_getServiceName(); 427 428 return aRet; 429 } 430 431 OUString OPipeTest_getServiceName() throw() 432 { 433 return OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICE_NAME ) ); 434 } 435 436 OUString OPipeTest_getImplementationName() throw() 437 { 438 return OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) ); 439 } 440