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
WriteToStreamThread(Reference<XOutputStream> xOutput,int iMax)65 WriteToStreamThread( Reference< XOutputStream > xOutput , int iMax )
66 {
67 m_output = xOutput;
68 m_iMax = iMax;
69 }
70
~WriteToStreamThread()71 virtual ~WriteToStreamThread() {}
72
73
74 protected:
75
76 /// Working method which should be overridden.
run()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 */
onTerminated()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
OPipeTest(const Reference<XMultiServiceFactory> & rFactory)140 OPipeTest::OPipeTest( const Reference< XMultiServiceFactory > &rFactory )
141 {
142
143 }
144
~OPipeTest()145 OPipeTest::~OPipeTest()
146 {
147
148 }
149
150
151
testInvariant(const OUString & TestName,const Reference<XInterface> & TestObject)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
test(const OUString & TestName,const Reference<XInterface> & TestObject,sal_Int32 hTestHandle)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
testPassed(void)216 sal_Bool OPipeTest::testPassed(void) throw (RuntimeException)
217 {
218 return m_seqErrors.getLength() == 0;
219 }
220
221
getErrors(void)222 Sequence< OUString > OPipeTest::getErrors(void) throw (RuntimeException)
223 {
224 return m_seqErrors;
225 }
226
227
getErrorExceptions(void)228 Sequence< Any > OPipeTest::getErrorExceptions(void) throw (RuntimeException)
229 {
230 return m_seqExceptions;
231 }
232
233
getWarnings(void)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
testSimple(const Reference<XInterface> & r)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
testBufferResizing(const Reference<XInterface> & r)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
testMultithreading(const Reference<XInterface> & r)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 **/
OPipeTest_CreateInstance(const Reference<XMultiServiceFactory> & rSMgr)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
OPipeTest_getSupportedServiceNames(void)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
OPipeTest_getServiceName()427 OUString OPipeTest_getServiceName() throw()
428 {
429 return OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICE_NAME ) );
430 }
431
OPipeTest_getImplementationName()432 OUString OPipeTest_getImplementationName() throw()
433 {
434 return OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
435 }
436