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 114 virtual sal_Int32 SAL_CALL test( const OUString& TestName, 115 const Reference < XInterface >& TestObject, 116 sal_Int32 hTestHandle); 117 118 virtual sal_Bool SAL_CALL testPassed(void) ; 119 virtual Sequence< OUString > SAL_CALL getErrors(void) ; 120 virtual Sequence< Any > SAL_CALL getErrorExceptions(void); 121 virtual Sequence< OUString > SAL_CALL getWarnings(void); 122 123 private: 124 void testSimple( const Reference < XInterface > & ); 125 void testBufferResizing( const Reference < XInterface > & ); 126 void testMultithreading( const Reference < XInterface > & ); 127 128 private: 129 Sequence<Any> m_seqExceptions; 130 Sequence<OUString> m_seqErrors; 131 Sequence<OUString> m_seqWarnings; 132 133 }; 134 135 136 137 OPipeTest::OPipeTest( const Reference< XMultiServiceFactory > &rFactory ) 138 { 139 140 } 141 142 OPipeTest::~OPipeTest() 143 { 144 145 } 146 147 148 149 void OPipeTest::testInvariant( const OUString& TestName, const Reference < XInterface >& TestObject ) 150 { 151 Reference< XServiceInfo > info( TestObject, UNO_QUERY ); 152 ERROR_ASSERT( info.is() , "XServiceInfo not supported !" ); 153 if( info.is() ) 154 { 155 ERROR_ASSERT( info->supportsService( TestName ), "XServiceInfo test failed" ); 156 ERROR_ASSERT( ! info->supportsService( 157 OUString( RTL_CONSTASCII_USTRINGPARAM("bla bluzb") ) ), "XServiceInfo test failed" ); 158 } 159 160 } 161 162 163 sal_Int32 OPipeTest::test( 164 const OUString& TestName, 165 const Reference < XInterface >& TestObject, 166 sal_Int32 hTestHandle) 167 { 168 if( OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.io.Pipe") ) == TestName ) { 169 try 170 { 171 if( 0 == hTestHandle ) { 172 testInvariant( TestName , TestObject ); 173 } 174 else if( 1 == hTestHandle ) { 175 testSimple( TestObject ); 176 } 177 else if( 2 == hTestHandle ) { 178 testBufferResizing( TestObject ); 179 } 180 else if( 3 == hTestHandle ) { 181 testMultithreading( TestObject ); 182 } 183 } 184 catch( Exception & e ) 185 { 186 OString s = OUStringToOString( e.Message , RTL_TEXTENCODING_ASCII_US ); 187 BUILD_ERROR( 0 , s.getStr() ); 188 } 189 catch( ... ) 190 { 191 BUILD_ERROR( 0 , "unknown exception (Exception is not base class)" ); 192 } 193 194 hTestHandle ++; 195 196 if( 4 == hTestHandle ) 197 { 198 // all tests finished. 199 hTestHandle = -1; 200 } 201 } 202 else { 203 throw IllegalArgumentException(); 204 } 205 return hTestHandle; 206 } 207 208 209 210 sal_Bool OPipeTest::testPassed(void) 211 { 212 return m_seqErrors.getLength() == 0; 213 } 214 215 216 Sequence< OUString > OPipeTest::getErrors(void) 217 { 218 return m_seqErrors; 219 } 220 221 222 Sequence< Any > OPipeTest::getErrorExceptions(void) 223 { 224 return m_seqExceptions; 225 } 226 227 228 Sequence< OUString > OPipeTest::getWarnings(void) 229 { 230 return m_seqWarnings; 231 } 232 233 234 /*** 235 * the test methods 236 * 237 ****/ 238 239 240 void OPipeTest::testSimple( const Reference < XInterface > &r ) 241 { 242 243 Reference< XInputStream > input( r , UNO_QUERY ); 244 Reference < XOutputStream > output( r , UNO_QUERY ); 245 246 ERROR_ASSERT( input.is() , "queryInterface on XInputStream failed" ); 247 ERROR_ASSERT( output.is() , "queryInterface onXOutputStream failed" ); 248 249 // basic read/write 250 Sequence<sal_Int8> seqWrite = createSeq( "Hallo, du Ei !" ); 251 252 Sequence<sal_Int8> seqRead; 253 for( int i = 0 ; i < 5000 ; i ++ ) { 254 output->writeBytes( seqWrite ); 255 input->readBytes( seqRead , input->available() ); 256 257 ERROR_ASSERT( ! strcmp( (char *) seqWrite.getArray() , (char * )seqRead.getArray() ) , 258 "error during read/write/skip" ); 259 ERROR_ASSERT( 0 == input->available() , 260 "error during read/write/skip" ); 261 262 // available shouldn't return a negative value 263 input->skipBytes( seqWrite.getLength() - 5 ); 264 ERROR_ASSERT( 0 == input->available() , "wrong available after skip" ); 265 266 // 5 bytes should be available 267 output->writeBytes( seqWrite ); 268 ERROR_ASSERT( 5 == input->available() , "wrong available after skip/write " ); 269 270 input->readBytes( seqRead , 5 ); 271 ERROR_ASSERT( ! strcmp( (char*) seqRead.getArray() , 272 (char*) &( seqWrite.getArray()[seqWrite.getLength()-5] ) ), 273 "write/read mismatich" ); 274 275 } 276 277 output->writeBytes( seqWrite ); 278 ERROR_ASSERT( seqWrite.getLength() == input->available(), "wrong available() after write" ); 279 280 ERROR_ASSERT( 10 == input->readSomeBytes( seqRead , 10 ) , "maximal number of bytes ignored" ); 281 ERROR_ASSERT( seqWrite.getLength() -10 == input->readSomeBytes( seqRead , 100 ) , 282 "something wrong with readSomeBytes" ); 283 284 285 output->closeOutput(); 286 try{ 287 output->writeBytes( Sequence<sal_Int8> (100) ); 288 ERROR_ASSERT( 0 , "writing on a closed stream does not cause an exception" ); 289 } 290 catch (IOException & ) 291 { 292 } 293 294 ERROR_ASSERT(! input->readBytes( seqRead , 1 ), "eof not found !" ); 295 296 input->closeInput(); 297 try 298 { 299 input->readBytes( seqRead , 1 ); 300 ERROR_ASSERT( 0 , "reading from a closed stream does not cause an exception" ); 301 } 302 catch( IOException & ) { 303 } 304 305 try 306 { 307 input->available( ); 308 ERROR_ASSERT( 0 , "calling available from a closed stream should thrown an io exception" ); 309 } 310 catch( IOException & ) 311 { 312 313 } 314 try 315 { 316 input->skipBytes(42 ); 317 ERROR_ASSERT( 0 , "calling available from a closed stream should thrown an io exception" ); 318 } 319 catch( IOException & ) 320 { 321 322 } 323 } 324 325 void OPipeTest::testBufferResizing( const Reference < XInterface > &r ) 326 { 327 int i; 328 int iMax = 20000; 329 Reference< XInputStream > input( r , UNO_QUERY ); 330 Reference < XOutputStream > output( r , UNO_QUERY ); 331 332 ERROR_ASSERT( input.is() , "queryInterface on XInputStream failed" ); 333 ERROR_ASSERT( output.is() , "queryInterface on XOutputStream failed" ); 334 335 Sequence<sal_Int8> seqRead; 336 337 // this is just to better check the 338 // internal buffers 339 output->writeBytes( Sequence<sal_Int8>(100) ); 340 Sequence< sal_Int8 > dummy; 341 input->readBytes( dummy , 100); 342 343 for( i = 0 ; i < iMax ; i ++ ) { 344 output->writeBytes( createIntSeq( i ) ); 345 } 346 347 for( i = 0 ; i < iMax ; i ++ ) { 348 input->readBytes( seqRead, createIntSeq(i).getLength() ); 349 ERROR_ASSERT( ! strcmp( (char*) seqRead.getArray() , 350 (char*) createIntSeq(i).getArray() ) , 351 "written/read mismatch\n" ); 352 } 353 354 output->closeOutput(); 355 ERROR_ASSERT( ! input->readBytes( seqRead , 1 ) , "eof not reached !" ); 356 input->closeInput(); 357 } 358 359 360 361 void OPipeTest::testMultithreading( const Reference < XInterface > &r ) 362 { 363 364 int i; 365 int iMax = 30000; 366 367 Reference< XInputStream > input( r , UNO_QUERY ); 368 Reference < XOutputStream > output( r , UNO_QUERY ); 369 370 ERROR_ASSERT( input.is() , "queryInterface on XInputStream failed" ); 371 ERROR_ASSERT( output.is() , "queryInterface on XOutputStream failed" ); 372 373 Sequence<sal_Int8> seqRead; 374 375 // deletes itself 376 Thread *p = new WriteToStreamThread( output, iMax ); 377 378 ERROR_ASSERT( p , "couldn't create thread for testing !\n" ); 379 380 p->create(); 381 382 for( i = 0 ; sal_True ; i ++ ) { 383 if( 0 == input->readBytes( seqRead, createIntSeq(i).getLength() ) ) { 384 // eof reached ! 385 break; 386 } 387 388 ERROR_ASSERT( ! strcmp( (char*) seqRead.getArray() , 389 (char*) createIntSeq(i).getArray() ) , 390 "written/read mismatch\n" ); 391 } 392 393 ERROR_ASSERT( i == iMax , "less elements read than written !"); 394 input->closeInput(); 395 } 396 397 398 399 /** 400 * for external binding 401 * 402 * 403 **/ 404 Reference < XInterface > SAL_CALL OPipeTest_CreateInstance( const Reference< XMultiServiceFactory> & rSMgr ) 405 { 406 OPipeTest *p = new OPipeTest( rSMgr ); 407 Reference< XInterface > x ( SAL_STATIC_CAST( OWeakObject * , p ) ); 408 return x; 409 } 410 411 412 413 Sequence<OUString> OPipeTest_getSupportedServiceNames(void) throw() 414 { 415 Sequence<OUString> aRet(1); 416 aRet.getArray()[0] = OPipeTest_getServiceName(); 417 418 return aRet; 419 } 420 421 OUString OPipeTest_getServiceName() throw() 422 { 423 return OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICE_NAME ) ); 424 } 425 426 OUString OPipeTest_getImplementationName() throw() 427 { 428 return OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) ); 429 } 430