xref: /AOO41X/main/extensions/workben/pythonautotest.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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