xref: /trunk/main/extensions/workben/pythonautotest.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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_extensions.hxx"
30 #include <stdio.h>
31 #include <stardiv/uno/repos/implementationregistration.hxx>
32 #include <stardiv/uno/script/script.hxx>
33 #include <stardiv/uno/beans/exactname.hxx>
34 
35 #include <rtl/ustring.hxx>
36 #include <vos/dynload.hxx>
37 #include <vos/diagnose.hxx>
38 #include <usr/services.hxx>
39 #include <vcl/svapp.hxx>
40 #include <usr/ustring.hxx>
41 #include <usr/weak.hxx>
42 #include <tools/string.hxx>
43 #include <vos/conditn.hxx>
44 
45 using namespace rtl;
46 using namespace vos;
47 using namespace usr;
48 
49 #define PCHAR_TO_USTRING(x) StringToOUString(String(x),CHARSET_SYSTEM)
50 #define USTRING_TO_PCHAR(x) OUStringToString(x , CHARSET_DONTKNOW ).GetCharStr()
51 
52 
53 
54 
55 
56 /*****
57 *
58 * A Test root object !
59 *
60 *****/
61 class MyPythonRoot :
62         public XInvokation,
63         public OWeakObject
64 {
65 public:
66     MyPythonRoot() { m_iTestValue = 15; }
67     BOOL                queryInterface( Uik aUik, XInterfaceRef & rOut );
68     void                acquire()                        { OWeakObject::acquire(); }
69     void                release()                        { OWeakObject::release(); }
70     void*               getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }
71 
72 public:
73     XIntrospectionAccessRef getIntrospection(void) const        THROWS( (UsrSystemException) )
74                 { return XIntrospectionAccessRef();  }
75 
76     UsrAny                  invoke( const UString& FunctionName,
77                                     const Sequence< UsrAny >& Params,
78                                     Sequence< INT16 >& OutParamIndex,
79                                     Sequence< UsrAny >& OutParam)
80                                                                 THROWS( (   IllegalArgumentException,
81                                                                             CannotConvertException,
82                                                                             InvocationTargetException,
83                                                                             UsrSystemException) );
84     void                    setValue(const UString& PropertyName, const UsrAny& Value)
85                                                                 THROWS( (   UnknownPropertyException,
86                                                                             CannotConvertException,
87                                                                             InvocationTargetException,
88                                                                             UsrSystemException) );
89 
90     UsrAny                  getValue(const UString& PropertyName)
91                                                                 THROWS( (   UnknownPropertyException,
92                                                                             UsrSystemException) );
93     BOOL                    hasMethod(const UString& Name) const THROWS( (UsrSystemException) );
94     BOOL                    hasProperty(const UString& Name) const THROWS( (UsrSystemException) );
95 
96 
97     void getTestValueViaInout( int &inout )
98         { inout = m_iTestValue; }
99 
100     INT32 getTestValue() const
101         { return m_iTestValue; }
102 
103     void setTestValue( INT32 i )
104         { m_iTestValue = i; }
105 
106     void printTestValue()
107         { fprintf( stderr, "TestValue : %d\n" , getTestValue() ); }
108 
109     void addTestValue( INT32 i )
110         { m_iTestValue += i; }
111 
112 private:
113 
114     INT32 m_iTestValue;
115 };
116 
117 BOOL MyPythonRoot::queryInterface( Uik aUik, XInterfaceRef &rOut )
118 {
119     if( aUik == XInvokation::getSmartUik() ) {
120         rOut = ( XInvokation * ) this;
121     }
122     else {
123         return OWeakObject::queryInterface( aUik , rOut );
124     }
125     return TRUE;
126 
127 }
128 
129 UsrAny  MyPythonRoot::invoke(   const UString& FunctionName,
130                                 const Sequence< UsrAny >& Params,
131                                 Sequence< INT16 >& OutParamIndex,
132                                 Sequence< UsrAny >& OutParam)
133                                                                 THROWS( (   IllegalArgumentException,
134                                                                             CannotConvertException,
135                                                                             InvocationTargetException,
136                                                                             UsrSystemException) )
137 {
138     if( L"printTestValue" == FunctionName ) {
139         printTestValue();
140     }
141     else if( L"addTestValue" == FunctionName ) {
142         addTestValue( Params.getConstArray()[0].getINT32() );
143     }
144     else if( L"getTestValueViaInout" == FunctionName ) {
145         int i = Params.getConstArray()[0].getINT32();
146         getTestValueViaInout( i );
147         OutParam.getArray()[0].setINT32( i );
148     }
149     else {
150         THROW( InvocationTargetException() );
151     }
152 
153     return UsrAny();
154 }
155 
156 void    MyPythonRoot::setValue(const UString& PropertyName, const UsrAny& Value)
157                                                                 THROWS( (   UnknownPropertyException,
158                                                                             CannotConvertException,
159                                                                             InvocationTargetException,
160                                                                             UsrSystemException) )
161 {
162     if( L"TestValue" == PropertyName ) {
163         setTestValue( Value.getINT32() );
164     }
165     else {
166         THROW( UnknownPropertyException() );
167     }
168 }
169 
170 UsrAny  MyPythonRoot::getValue(const UString& PropertyName)
171                                                                 THROWS( (   UnknownPropertyException,
172                                                                             UsrSystemException) )
173 {
174     UsrAny aRet;
175 
176     if( L"TestValue" == PropertyName ) {
177         aRet.setINT32( getTestValue() );
178     }
179     else {
180         THROW( UnknownPropertyException() );
181     }
182 
183     return aRet;
184 }
185 
186 
187 BOOL    MyPythonRoot::hasMethod(const UString& Name) const      THROWS( (UsrSystemException) )
188 {
189     if( L"printTestValue" == Name ) {
190         return TRUE;
191     }
192     else if( L"addTestValue" == Name ) {
193         return TRUE;
194     }
195     else if( L"getTestValueViaInout" == Name ) {
196         return TRUE;
197     }
198     return FALSE;
199 }
200 
201 
202 BOOL    MyPythonRoot::hasProperty(const UString& Name) const THROWS( (UsrSystemException) )
203 {
204     if( L"TestValue" == Name ) {
205         return TRUE;
206     }
207 
208     return FALSE;
209 }
210 
211 
212 /*****
213 *
214 * A test engine listener to check the debug interface
215 *
216 *****/
217 class TestListener :
218     public XEngineListener,
219     public OWeakObject
220 {
221 public:
222 
223     TestListener()
224     {
225         m_pDebuggingRef = 0;
226     }
227 
228 
229     TestListener( XDebuggingRef *p )
230     {
231         attach( p  );
232     }
233 
234     ~TestListener()
235     {
236         if( m_pDebuggingRef ) {
237             detach();
238         }
239     }
240 
241     BOOL                queryInterface( Uik aUik, XInterfaceRef & rOut );
242     void                acquire()                        { OWeakObject::acquire(); }
243     void                release()                        { OWeakObject::release(); }
244     void*               getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }
245 
246 
247     void attach( XDebuggingRef *p )
248     {
249         m_pDebuggingRef = p;
250     }
251 
252     void detach( );
253 
254 
255     virtual void disposing( const EventObject &o )
256     {
257         if( m_pDebuggingRef ) {
258             detach();
259         }
260     }
261     virtual void interrupt(const InterruptEngineEvent& Evt) THROWS( (UsrSystemException) )
262     {
263     }
264 
265     virtual void running(const EventObject& Evt) THROWS( (UsrSystemException) )
266     {
267         (*m_pDebuggingRef)->stop();
268 
269         m_aDebugCondition.set();
270     }
271 
272     virtual void finished(const FinishEngineEvent& Evt) THROWS( (UsrSystemException) )
273     {
274         m_aDebugCondition.set();
275     }
276 
277 
278     void cmdLine();
279 protected:
280 
281     OCondition m_aDebugCondition;
282     XDebuggingRef *m_pDebuggingRef;
283 };
284 
285 
286 
287 void TestListener::cmdLine()
288 {
289     // Condition is set by running listener
290     m_aDebugCondition.wait();
291     m_aDebugCondition.reset();
292     (*m_pDebuggingRef)->doContinue();
293     m_aDebugCondition.wait();
294 }
295 
296 void TestListener::detach()
297 {
298     OSL_ASSERT( m_pDebuggingRef );
299 
300     m_pDebuggingRef = 0;
301 }
302 
303 BOOL TestListener::queryInterface( Uik aUik, XInterfaceRef & rOut )
304 {
305     if( aUik == XEngineListener::getSmartUik() )
306         rOut = (XEngineListener*)this;
307     else
308         return OWeakObject::queryInterface( aUik, rOut );
309     return TRUE;
310 }
311 
312 
313 void checkInvokation( const XInvokationRef &xInvoke )
314 {
315     UsrAny anyList;
316 
317     // check exporting an object as an invokation
318     OSL_ASSERT( xInvoke->hasProperty( L"list" ) );
319     anyList = xInvoke->getValue( L"list" );
320 
321     OSL_ASSERT( anyList.getReflection() == XInvokation_getReflection() );
322     XInvokationRef *pRef = ( XInvokationRef * ) anyList.get();
323     OSL_ASSERT( (*pRef).is() );
324 
325     OSL_ASSERT( (*pRef)->hasMethod( L"append"  ) );
326     OSL_ASSERT( (*pRef)->hasMethod( L"count" ) );
327 
328     Sequence<UsrAny> seq(1);
329     UsrAny any( (INT32) 1);
330     (seq.getArray())[0] = any;
331 
332     any = (*pRef)->invoke( L"count" , seq , Sequence<INT16>(), Sequence<UsrAny>() );
333     int nOldSize = any.getINT32();
334 
335     any = (*pRef)->invoke( L"append" , seq  , Sequence<INT16>(), Sequence<UsrAny>() );
336     any = (*pRef)->invoke( L"count" , seq , Sequence<INT16>(), Sequence<UsrAny>() );
337 
338     OSL_ASSERT( nOldSize + 1 == any.getINT32() );
339 }
340 
341 // just for testing !
342 class PythonCodeLibrary :
343         public XLibraryAccess,
344         public OWeakObject
345 {
346 
347     BOOL                queryInterface( Uik aUik, XInterfaceRef & rOut );
348     void                acquire()                        { OWeakObject::acquire(); }
349     void                release()                        { OWeakObject::release(); }
350     void*               getImplementation(Reflection *p) { return OWeakObject::getImplementation(p); }
351 
352 
353     virtual BOOL isFunction(const UString& FunctionName)            THROWS( (UsrSystemException) )
354     {
355         return FALSE;
356     }
357 
358     virtual BOOL isValidPath(const UString& PathName)               THROWS( (UsrSystemException) )
359     {
360         return FALSE;
361     }
362 
363     virtual Sequence< UString > getModuleNames(void)                THROWS( (UsrSystemException) )
364     {
365         return Sequence<UString> ();
366     }
367 
368     virtual UString getModuleSource(const UString& ModulName)       THROWS( (UsrSystemException) )
369     {
370         if( ModulName == L"testmodul" ) {
371             return UString( L"def testmethod():\n"
372                             L"  return 42\n");
373         }
374         return UString();
375     }
376 
377     virtual Sequence< BYTE > getModuleCode(const UString& ModuleName) THROWS( (UsrSystemException) )
378     {
379         return Sequence< BYTE > ();
380     }
381 
382     virtual UString getFunctionSource(const UString& FunctionName) THROWS( (UsrSystemException) )
383     {
384         return UString();
385     }
386     virtual Sequence< BYTE > getFunctionCode(const UString& FunctionName) THROWS( (UsrSystemException) )
387     {
388         return Sequence< BYTE > ();
389     }
390 };
391 
392 BOOL PythonCodeLibrary::queryInterface( Uik aUik, XInterfaceRef & rOut )
393 {
394     if( XLibraryAccess::getSmartUik() == aUik ) {
395         rOut = (XLibraryAccess* ) this;
396     }
397     else {
398         return OWeakObject::queryInterface( aUik , rOut );
399     }
400 
401     return TRUE;
402 }
403 
404 
405 
406 /*
407  * main.
408  */
409 int __LOADONCALLAPI main (int argc, char **argv)
410 {
411     // necessary startup code
412     XMultiServiceFactoryRef xSMgr = createRegistryServiceManager();
413     registerUsrServices( xSMgr );
414     setProcessServiceManager( xSMgr );
415 
416     XInterfaceRef x = xSMgr->createInstance( L"stardiv.uno.repos.ImplementationRegistration" );
417     XImplementationRegistrationRef xReg( x, USR_QUERY );
418     sal_Char szBuf[1024];
419 
420     ORealDynamicLoader::computeModuleName( "pythonengine", szBuf, 1024 );
421     UString aDllName( StringToOUString( szBuf, CHARSET_SYSTEM ) );
422     xReg->registerImplementation( L"stardiv.loader.SharedLibrary", aDllName, XSimpleRegistryRef() );
423 
424     x = xSMgr->createInstance( L"stardiv.script.Python" );
425     XEngineRef xEngine( x, USR_QUERY );
426     XInvokationRef xInvoke(  x, USR_QUERY );
427     XDebuggingRef xDebug( x , USR_QUERY );
428 
429     XInterfaceRef rRoot( (XInvokation * )new MyPythonRoot , USR_QUERY );
430     xEngine->setRoot( rRoot );
431 
432 
433     // execute a simple script
434     xEngine->run(   L"nIntTest = 5\n"
435                     L"list = [2,3,4]\n" , XInterfaceRef(), Sequence<UsrAny> () );
436 
437     /****
438     *
439     * Xinvokation - Test
440     *
441     *****/
442     // get/set an int !
443     {
444         OSL_ASSERT( xInvoke->hasProperty( L"nIntTest" ) );
445         UsrAny any = xInvoke->getValue( L"nIntTest" );
446 
447         OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG );
448         OSL_ASSERT( any.getINT32() == 5 );
449 
450         // simple test: set an int !
451         xInvoke->setValue( L"nIntTest" , UsrAny( (INT32) 10 ) );
452         any = xInvoke->getValue( L"nIntTest" );
453 
454         OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG );
455         OSL_ASSERT( any.getINT32() == 10 );
456     }
457 
458     //  call a python method !
459     {
460         xEngine->run( L"def foo():\n"
461                       L"    return 'this is foo'\n" , XInterfaceRef() , Sequence<UsrAny> () );
462         OSL_ASSERT( xInvoke->hasMethod( L"foo" ) );
463         UsrAny any = xInvoke->invoke(   L"foo" ,
464                                         Sequence<UsrAny>(),
465                                         Sequence<INT16>() ,
466                                         Sequence<UsrAny> () );
467         OSL_ASSERT( any.getString() == L"this is foo" );
468     }
469 
470 
471     // check exception handling !
472     {
473         try {
474             xInvoke->invoke( L"foo" , Sequence<UsrAny>(1) , Sequence<INT16>(), Sequence<UsrAny> () );
475             // wrong number of arguments
476             OSL_ASSERT( 0 );
477         }
478         catch ( IllegalArgumentException& e ) {
479         }
480         catch ( InvocationTargetException& e ) {
481         }
482         catch ( CannotConvertException& e ) {
483             // empty any cannot be converted
484         }
485     }
486 
487     // check InOut-Parameter
488     checkInvokation( xInvoke );
489 
490     /*******
491     *
492     * Check Introspection Access
493     *
494     *******/
495     {
496         XIntrospectionAccessRef xIntrospection = xInvoke->getIntrospection();
497         OSL_ASSERT( xIntrospection.is() );
498 
499         // no further test, simply call them
500         xIntrospection->getMethods(0);
501         xIntrospection->getProperties(0);
502 
503         OSL_ASSERT( xIntrospection->getSuppliedMethodConcepts() == 0 );
504         OSL_ASSERT( xIntrospection->getSuppliedPropertyConcepts() == 0 );
505 
506         Property prop = xIntrospection->getProperty( L"nIntTest" ,0 );
507         OSL_ASSERT( prop.Name == L"nIntTest" );
508         OSL_ASSERT( prop.Type->getTypeClass() == TypeClass_LONG );
509 
510         XIdlMethodRef method = xIntrospection->getMethod( L"foo" , 0 );
511         OSL_ASSERT( method->getName() == L"foo" );
512     }
513 
514 
515     /******
516     *
517     * Multithreading test
518     *
519     *******/
520 
521     /******
522     *
523     * XDebuggingTest
524     *
525     ******/
526     // stop/doContinue + runAsync listener
527     {
528         // test hangs, if something is wrong
529 
530         TestListener *pListener = new TestListener( &xDebug );
531         XEngineListenerRef ref( (XEngineListener * ) pListener , USR_QUERY );
532 
533         // single listener check !
534         xEngine->runAsync( L"pass\n"
535                             , XInterfaceRef() , Sequence<UsrAny> () , ref );
536         pListener->cmdLine();
537     }
538 
539     // ListenerAdministration check !
540     {
541         // test hangs, if something is wrong
542 
543         TestListener *pListener = new TestListener( &xDebug );
544         XEngineListenerRef ref( (XEngineListener * ) pListener , USR_QUERY );
545 
546         // engine listener check !
547         xEngine->addEngineListener( ref );
548         xEngine->runAsync( L"pass\n"
549                             , XInterfaceRef() , Sequence<UsrAny> () , XEngineListenerRef() );
550         pListener->cmdLine();
551         xEngine->removeEngineListener( ref);
552 
553     }
554 
555     // check the import mechanism
556     {
557         XLibraryAccessRef xLibrary( ( XLibraryAccess * ) new PythonCodeLibrary , USR_QUERY );
558         xEngine->setLibraryAccess( xLibrary );
559 
560         xEngine->run(   L"import testmodul\n"
561                         L"x = testmodul.testmethod()\n" , XInterfaceRef() , Sequence<UsrAny>() );
562         UsrAny any = xInvoke->getValue( L"x" );
563         OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG );
564         OSL_ASSERT( any.getINT32() == 42 );
565     }
566 
567     // check other imports
568     {
569         // Check, if the libraries are available at run time
570         xEngine->run(   L"import math\n"
571                         L"dMathTest = math.exp(0)\n"  , XInterfaceRef() , Sequence<UsrAny> () );
572 
573         OSL_ASSERT( xInvoke->hasProperty( L"dMathTest" ) );
574         UsrAny any = xInvoke->getValue( L"dMathTest" );
575 
576         OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_DOUBLE );
577         OSL_ASSERT( any.getDouble() == 1. );
578     }
579 
580     // Test connection to root object !
581     {
582         xEngine->run(   L"x = stardiv.root.TestValue\n"
583                         L"y = stardiv.inout(5)\n"
584                         L"stardiv.root.getTestValueViaInout(y)\n"
585                         L"z = y.value\n" , XInterfaceRef() , Sequence<UsrAny> () );
586 
587         UsrAny any = xInvoke->getValue( L"x" );
588         OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG );
589         OSL_ASSERT( any.getINT32() == 15 );
590 
591         any = xInvoke->getValue( L"z" );
592         OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_LONG );
593         OSL_ASSERT( any.getINT32() == 15 );
594     }
595 
596     // Test exactName interface
597     {
598         UsrAny any = xInvoke->getValue( L"__builtins__" );
599         OSL_ASSERT( any.getReflection()->getTypeClass() == TypeClass_INTERFACE );
600 
601         XInvokationRef rInv( *((XInterfaceRef *) any.get() ), USR_QUERY );
602         OSL_ASSERT( rInv.is() );
603 
604         XExactNameRef rName( *((XInterfaceRef*) any.get() ), USR_QUERY );
605         OSL_ASSERT( rName.is() );
606 
607         UString str = rName->getExactName( L"SYNTAXERROR" );
608         OSL_ASSERT( str.len() );
609     }
610 
611 
612     // Test exactName interface of the engine itself
613     {
614         XExactNameRef rName( xInvoke , USR_QUERY );
615         OSL_ASSERT( rName.is() );
616         UString str = rName->getExactName( L"STARDIV" );
617         OSL_ASSERT( str.len() );
618     }
619 
620 
621     return 0;
622 }
623 
624