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