xref: /AOO41X/main/sal/qa/osl/module/osl_Module.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_sal.hxx"
30 
31 //------------------------------------------------------------------------
32 // include files
33 //------------------------------------------------------------------------
34 #include <osl_Module_Const.h>
35 
36 using namespace	osl;
37 using namespace	rtl;
38 
39 
40 //------------------------------------------------------------------------
41 // helper functions and classes
42 //------------------------------------------------------------------------
43 
44 /** print Boolean value.
45 */
46 inline void printBool( sal_Bool bOk )
47 {
48 	t_print("#printBool# " );
49 	( sal_True == bOk ) ? t_print("TRUE!\n" ): t_print("FALSE!\n" );
50 }
51 
52 /** print a UNI_CODE String.
53 */
54 inline void printUString( const ::rtl::OUString & str )
55 {
56 	rtl::OString aString;
57 
58 	t_print("#printUString_u# " );
59 	aString = ::rtl::OUStringToOString( str, RTL_TEXTENCODING_ASCII_US );
60 	t_print("%s\n", aString.getStr( ) );
61 }
62 
63 /** get dll file URL.
64 */
65 inline ::rtl::OUString getDllURL( void )
66 {
67 #if ( defined WNT )	       // lib in Unix and lib in Windows are not same in file name.
68 	::rtl::OUString libPath( rtl::OUString::createFromAscii( "Module_DLL.dll" ) );
69 #else
70 	::rtl::OUString libPath( rtl::OUString::createFromAscii( "libModule_DLL.so" ) );
71 #endif
72 
73 	::rtl::OUString dirPath, dllPath;
74 	osl::Module::getUrlFromAddress( ( void* ) &getDllURL, dirPath );
75 	dirPath = dirPath.copy( 0, dirPath.lastIndexOf('/') + 1);
76 	osl::FileBase::getAbsoluteFileURL( dirPath, libPath, dllPath );
77 
78 	return dllPath;
79 }
80 
81 /** print a UNI_CODE file name.
82 */
83 inline void printFileName( const ::rtl::OUString & str )
84 {
85 	rtl::OString aString;
86 
87 	t_print("#printFileName_u# " );
88 	aString = ::rtl::OUStringToOString( str, RTL_TEXTENCODING_ASCII_US );
89 	t_print("%s\n", aString.getStr( ) );
90 }
91 
92 inline sal_Bool isURL( const ::rtl::OUString pathname )
93 {
94 	::rtl::OUString aPreURL( rtl::OUString::createFromAscii( "file:///" ) );
95 	return ( ( pathname.indexOf( aPreURL ) == 0 ) ? sal_True : sal_False );
96 }
97 
98 /** create a temp test directory using OUString name of full qualified URL or system path.
99 */
100 inline void createTestDirectory( const ::rtl::OUString dirname )
101 {
102 	::rtl::OUString     aPathURL   = dirname.copy( 0 );
103 	::osl::FileBase::RC	nError;
104 
105 	if ( !isURL( dirname ) )
106 		::osl::FileBase::getFileURLFromSystemPath( dirname, aPathURL ); //convert if not full qualified URL
107 	nError = ::osl::Directory::create( aPathURL );
108 	CPPUNIT_ASSERT_MESSAGE( "In createTestDirectory Function: creation: ", ( ::osl::FileBase::E_None == nError ) || ( nError == ::osl::FileBase::E_EXIST ) );
109 }
110 
111 /** delete a temp test directory using OUString name of full qualified URL or system path.
112 */
113 inline void deleteTestDirectory( const ::rtl::OUString dirname )
114 {
115 	::rtl::OUString     aPathURL   = dirname.copy( 0 );
116 	::osl::FileBase::RC	nError;
117 	if ( !isURL( dirname ) )
118 		::osl::FileBase::getFileURLFromSystemPath( dirname, aPathURL ); //convert if not full qualified URL
119 
120 	::osl::Directory testDir( aPathURL );
121 	if ( testDir.isOpen( ) == sal_True )
122 	{
123         	testDir.close( );  //close if still open.
124     	}
125 
126 	nError = ::osl::Directory::remove( aPathURL );
127  	CPPUNIT_ASSERT_MESSAGE( "In deleteTestDirectory function: remove ", ( ::osl::FileBase::E_None == nError ) || ( nError == ::osl::FileBase::E_NOENT ) );
128 }
129 
130 //check if the file exist
131 inline sal_Bool ifFileExist( const ::rtl::OUString & str )
132 {
133 	::rtl::OUString 	aUStr;
134 	if ( isURL( str ) )
135 		::osl::FileBase::getSystemPathFromFileURL( str, aUStr );
136 	else
137 		return sal_False;
138 
139 	::osl::File strFile( aUStr );
140 	::osl::FileBase::RC	nError = strFile.open( OpenFlag_Read );
141 	if ( ::File::E_NOENT == nError )
142 		return sal_False;
143 	else{
144 		strFile.close( );
145 		return sal_True;
146 	}
147 }
148 
149 /** detete a temp test file using OUString name.
150 */
151 inline void deleteTestFile( const ::rtl::OUString filename )
152 {
153 	::rtl::OUString	aPathURL   = filename.copy( 0 );
154 	::osl::FileBase::RC	nError;
155 
156 	if ( !isURL( filename ) )
157 		::osl::FileBase::getFileURLFromSystemPath( filename, aPathURL ); //convert if not full qualified URL
158 
159 	nError = ::osl::File::setAttributes( aPathURL, Attribute_GrpWrite| Attribute_OwnWrite| Attribute_OthWrite ); // if readonly, make writtenable.
160 	CPPUNIT_ASSERT_MESSAGE( "In deleteTestFile Function: set writtenable ", ( ::osl::FileBase::E_None == nError ) || ( ::osl::FileBase::E_NOENT == nError ) );
161 
162 	nError = ::osl::File::remove( aPathURL );
163 	CPPUNIT_ASSERT_MESSAGE( "In deleteTestFile Function: remove ", ( ::osl::FileBase::E_None == nError ) || ( nError == ::osl::FileBase::E_NOENT ) );
164 }
165 
166 
167 //------------------------------------------------------------------------
168 // test code start here
169 //------------------------------------------------------------------------
170 
171 namespace osl_Module
172 {
173 
174 	/** class and member function that is available for module test :
175 	*/
176 
177 	class testClass
178 	{
179 	public:
180 		static void myFunc()
181 		{
182 			t_print("#Sun Microsystem\n");
183 		};
184 	};
185 
186 
187 	/** testing the methods:
188 		Module();
189 		Module( const ::rtl::OUString& strModuleName, sal_Int32 nRtldMode = SAL_LOADMODULE_DEFAULT);
190 	*/
191 	class ctors : public CppUnit::TestFixture
192 	{
193 	public:
194 		sal_Bool bRes, bRes1;
195 
196 		void ctors_none( )
197 		{
198 			::osl::Module aMod;
199 			bRes = aMod.is();
200 
201 			CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor without parameter.",
202 									sal_False == bRes  );
203 		}
204 
205 		void ctors_name_mode( )
206 		{
207 			OUString aFileURL;
208             bRes = osl::Module::getUrlFromAddress( ( void* ) &::osl_Module::testClass::myFunc, aFileURL );
209 
210 			if ( !( bRes ) )
211 			{
212 				CPPUNIT_ASSERT_MESSAGE("Cannot locate current module.",  sal_False  );
213 			}
214 
215 			::osl::Module aMod( aFileURL );
216 			bRes = aMod.is( );
217 			aMod.unload( );
218 
219 			CPPUNIT_ASSERT_MESSAGE( "#test comment#: test constructor with load action.",
220 									sal_True == bRes  );
221 		}
222 
223 		CPPUNIT_TEST_SUITE( ctors );
224 		CPPUNIT_TEST( ctors_none );
225 		CPPUNIT_TEST( ctors_name_mode );
226 		CPPUNIT_TEST_SUITE_END( );
227 	}; // class ctors
228 
229 
230 	/** testing the methods:
231 		static sal_Bool getUrlFromAddress(void * addr, ::rtl::OUString & libraryUrl)
232 	*/
233 	class getUrlFromAddress : public CppUnit::TestFixture
234 	{
235 	public:
236 		sal_Bool bRes, bRes1;
237 
238 		void getUrlFromAddress_001( )
239 		{
240 			OUString aFileURL;
241             bRes = osl::Module::getUrlFromAddress( ( void* ) &::osl_Module::testClass::myFunc, aFileURL ) ;
242 			if ( !( bRes ) )
243 			{
244 				CPPUNIT_ASSERT_MESSAGE("Cannot locate current module.",  sal_False  );
245 			}
246 
247 			CPPUNIT_ASSERT_MESSAGE( "#test comment#: test get Module URL from address.",
248 									sal_True == bRes && 0 < aFileURL.lastIndexOf('/')  );
249 		}
250 
251 		void getUrlFromAddress_002( )
252 		{
253 			::osl::Module aMod( getDllURL( ) );
254 			FuncPtr pFunc = ( FuncPtr ) aMod.getSymbol( rtl::OUString::createFromAscii( "firstfunc" ) );
255 
256 			OUString aFileURL;
257             bRes = osl::Module::getUrlFromAddress( ( void* )pFunc, aFileURL );
258 			if ( !( bRes  ) )
259 			{
260 				CPPUNIT_ASSERT_MESSAGE("Cannot locate current module.",  sal_False  );
261 			}
262 			aMod.unload( );
263 
264 			CPPUNIT_ASSERT_MESSAGE( "#test comment#: load an external library, get its function address and get its URL.",
265 									sal_True == bRes && 0 < aFileURL.lastIndexOf('/') && aFileURL.equalsIgnoreAsciiCase( getDllURL( ) ) );
266 		}
267 
268 		/* tester comments: another case is getFunctionSymbol_001*/
269 
270 		CPPUNIT_TEST_SUITE( getUrlFromAddress );
271 		CPPUNIT_TEST( getUrlFromAddress_001 );
272 		CPPUNIT_TEST( getUrlFromAddress_002 );
273 		CPPUNIT_TEST_SUITE_END( );
274 	}; // class getUrlFromAddress
275 
276 
277 	/** testing the method:
278 		sal_Bool SAL_CALL load( const ::rtl::OUString& strModuleName,
279         	                                     sal_Int32 nRtldMode = SAL_LOADMODULE_DEFAULT)
280 	*/
281 	class load : public CppUnit::TestFixture
282 	{
283 	public:
284 		sal_Bool bRes, bRes1;
285 
286 		void load_001( )
287 		{
288 			::osl::Module aMod( getDllURL( ) );
289 			::osl::Module aMod1;
290 
291 			aMod1.load( getDllURL( ) );
292 			bRes = oslModule(aMod) == oslModule(aMod1);
293 			aMod.unload( );
294 			aMod1.unload( );
295 
296 			CPPUNIT_ASSERT_MESSAGE( "#test comment#: load function should do the same thing as constructor with library name.",
297 									sal_True == bRes  );
298 		}
299 		// load lib which is under a CJK directory
300 		void load_002( )
301 		{
302 #ifdef UNX
303 			//Can not get a CJK directory already exist, so here create one. Perhaps reason is encoding problem.
304 			::rtl::OUString aPidDirURL = rtl::OUString::createFromAscii( "file:///tmp/" ) + ::rtl::OUString::valueOf( ( long )getpid( ) );
305 			::rtl::OUString aMyDirURL = aPidDirURL + aKname;
306 			createTestDirectory( aPidDirURL );
307 			createTestDirectory( aMyDirURL );
308 
309 			::rtl::OUString aDLLURL = aMyDirURL + rtl::OUString::createFromAscii( "/libModule_DLL.so" );
310 			//check if the lib exist.
311 			//FIXME: if assert condition is false, the case will return, so the directory will not be clean-up
312 			CPPUNIT_ASSERT_MESSAGE( "#Source file is not exist. please manually clean-up directory and file under /tmp", ifFileExist( getDllURL( ) ) == sal_True );
313 			::osl::FileBase::RC nError = ::osl::File::copy( getDllURL( ), aDLLURL );
314 			CPPUNIT_ASSERT_MESSAGE( "#copy failed. please manually clean-up directory and file under /tmp", nError == ::osl::FileBase::E_None );
315 			//ifFileExist returned false but the file exist
316 			CPPUNIT_ASSERT_MESSAGE( "#This file is not exist, copy failed. please manually clean-up directory and file under /tmp", ifFileExist( aDLLURL ) == sal_True );
317 
318 			//test if can create a normal file
319 			::rtl::OUString aFileURL = aMyDirURL + rtl::OUString::createFromAscii( "/test_file" );
320 			::osl::File testFile( aFileURL );
321 			nError = testFile.open( OpenFlag_Create );
322 			CPPUNIT_ASSERT_MESSAGE( "#create failed. please manually clean-up directory and file under /tmp", nError == ::osl::FileBase::E_None );
323 			CPPUNIT_ASSERT_MESSAGE( "#This file is not exist, create failed. please manually clean-up directory and file under /tmp", ifFileExist( aFileURL ) == sal_True );
324 
325 			//load the copied dll
326 			::osl::Module aMod( aDLLURL );
327 			::osl::Module aMod1;
328 
329 			sal_Bool bOK = aMod1.load( aDLLURL );
330 			bRes = oslModule(aMod) == oslModule(aMod1);
331 			aMod.unload( );
332 			aMod1.unload( );
333 			deleteTestFile( aFileURL );
334 			deleteTestFile( aDLLURL );
335 			deleteTestDirectory( aMyDirURL );
336 			deleteTestDirectory( aPidDirURL );
337 
338 			CPPUNIT_ASSERT_MESSAGE( "#test comment#: load lib which is under a CJK directory.",
339 									sal_True == bRes && bOK == sal_True );
340 #endif
341 		}
342 
343 		CPPUNIT_TEST_SUITE( load );
344 		CPPUNIT_TEST( load_001 );
345 		CPPUNIT_TEST( load_002 );
346 		CPPUNIT_TEST_SUITE_END( );
347 	}; // class load
348 
349 
350 	/** testing the method:
351 		void SAL_CALL unload()
352 	*/
353 	class unload : public CppUnit::TestFixture
354 	{
355 	public:
356 		sal_Bool bRes, bRes1;
357 
358 		void unload_001( )
359 		{
360 			::osl::Module aMod( getDllURL( ) );
361 
362 			aMod.unload( );
363 			bRes = oslModule(aMod) ==NULL;
364 
365 			CPPUNIT_ASSERT_MESSAGE( "#test comment#: unload function should do the same thing as destructor.",
366 									sal_True == bRes  );
367 		}
368 
369 		CPPUNIT_TEST_SUITE( unload );
370 		CPPUNIT_TEST( unload_001 );
371 		CPPUNIT_TEST_SUITE_END( );
372 	}; // class unload
373 
374 
375 	/** testing the methods:
376 		sal_Bool SAL_CALL is() const
377 	*/
378 	class is : public CppUnit::TestFixture
379 	{
380 	public:
381 		sal_Bool bRes, bRes1;
382 
383 		void is_001( )
384 		{
385 			OUString aFileURL;
386             bRes = osl::Module::getUrlFromAddress( ( void* ) &::osl_Module::testClass::myFunc, aFileURL );
387 			if ( !( bRes  ) )
388 			{
389 				CPPUNIT_ASSERT_MESSAGE("Cannot locate current module - using executable instead",  sal_False  );
390 			}
391 
392 			::osl::Module aMod;
393 			bRes = aMod.is( );
394 			aMod.load( aFileURL );
395 			bRes1 = aMod.is( );
396 			aMod.unload( );
397 
398 			CPPUNIT_ASSERT_MESSAGE( "#test comment#: test if a module is a loaded module.",
399 									 sal_False == bRes && sal_True == bRes1);
400 		}
401 		CPPUNIT_TEST_SUITE( is );
402 		CPPUNIT_TEST( is_001 );
403 		CPPUNIT_TEST_SUITE_END( );
404 	}; // class is
405 
406 
407 	/** testing the methods:
408 		void* SAL_CALL getSymbol( const ::rtl::OUString& strSymbolName)
409 	*/
410 	class getSymbol : public CppUnit::TestFixture
411 	{
412 	public:
413 		sal_Bool bRes;
414 
415 		void getSymbol_001( )
416 		{
417 			::osl::Module aMod( getDllURL( ) );
418 			FuncPtr pFunc = ( FuncPtr ) aMod.getSymbol( rtl::OUString::createFromAscii( "firstfunc" ) );
419 			bRes = sal_False;
420 			if ( pFunc )
421 				bRes = pFunc( bRes );
422 			aMod.unload();
423 
424 			CPPUNIT_ASSERT_MESSAGE( "#test comment#: load a dll and call one function in it.",
425 									 sal_True == bRes );
426 		}
427 
428 		CPPUNIT_TEST_SUITE( getSymbol );
429 		CPPUNIT_TEST( getSymbol_001 );
430 		CPPUNIT_TEST_SUITE_END( );
431 	}; // class getSymbol
432 
433 
434 	/** testing the methods:
435 		operator oslModule() const
436 	*/
437 	class optr_oslModule : public CppUnit::TestFixture
438 	{
439 	public:
440 		sal_Bool bRes, bRes1;
441 
442 		void optr_oslModule_001( )
443 		{
444 			::osl::Module aMod;
445 			bRes = ( (oslModule)aMod == NULL );
446 
447 			aMod.load( getDllURL( ) );
448 			bRes1 = (oslModule)aMod != NULL;
449 
450 			aMod.unload( );
451 
452 			CPPUNIT_ASSERT_MESSAGE( "#test comment#: the m_Module of a Module instance will be NULL when is not loaded, it will not be NULL after loaded.",
453 									 sal_True == bRes && sal_True == bRes1);
454 		}
455 
456 		void optr_oslModule_002( )
457 		{
458 			::osl::Module aMod( getDllURL( ) );
459 			::rtl::OUString funcName(::rtl::OUString::createFromAscii( "firstfunc" ) );
460 
461 			FuncPtr pFunc = ( FuncPtr ) osl_getSymbol( (oslModule)aMod, funcName.pData );
462 			bRes = sal_False;
463 			if ( pFunc )
464 				bRes = pFunc( bRes );
465 
466 			aMod.unload();
467 
468 			CPPUNIT_ASSERT_MESSAGE( "#test comment#: use m_Module to call osl_getSymbol() function.",
469 									 sal_True == bRes  );
470 		}
471 
472 		CPPUNIT_TEST_SUITE( optr_oslModule );
473 		CPPUNIT_TEST( optr_oslModule_001 );
474 		CPPUNIT_TEST( optr_oslModule_002 );
475 		CPPUNIT_TEST_SUITE_END( );
476 	}; // class optr_oslModule
477 
478 	/** testing the methods:
479 		oslGenericFunction SAL_CALL getFunctionSymbol( const ::rtl::OUString& ustrFunctionSymbolName )
480 	*/
481 	class getFunctionSymbol : public CppUnit::TestFixture
482 	{
483 	public:
484 		sal_Bool bRes, bRes1;
485 
486 		void getFunctionSymbol_001( )
487 		{
488 			::osl::Module aMod( getDllURL( ) );
489 			oslGenericFunction oslFunc = aMod.getFunctionSymbol( rtl::OUString::createFromAscii( "firstfunc" ) );
490 			::rtl::OUString aLibraryURL;
491 			bRes = ::osl::Module::getUrlFromAddress( oslFunc, aLibraryURL);
492 			aMod.unload();
493 			printFileName( aLibraryURL );
494 
495 			CPPUNIT_ASSERT_MESSAGE( "#test comment#: load a dll and get its function addr and get its URL.",
496 				 sal_True == bRes && aLibraryURL.equalsIgnoreAsciiCase( getDllURL() ) );
497 		}
498 
499 		CPPUNIT_TEST_SUITE( getFunctionSymbol );
500 		CPPUNIT_TEST( getFunctionSymbol_001 );
501 		//CPPUNIT_TEST( getFunctionSymbol_002 );
502 		CPPUNIT_TEST_SUITE_END( );
503 	}; // class getFunctionSymbol
504 
505 // -----------------------------------------------------------------------------
506 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Module::ctors, "osl_Module");
507 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Module::getUrlFromAddress, "osl_Module");
508 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Module::load, "osl_Module");
509 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Module::unload, "osl_Module");
510 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Module::is, "osl_Module");
511 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Module::getSymbol, "osl_Module");
512 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Module::optr_oslModule, "osl_Module");
513 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(osl_Module::getFunctionSymbol, "osl_Module");
514 // -----------------------------------------------------------------------------
515 
516 } // namespace osl_Module
517 
518 // -----------------------------------------------------------------------------
519 
520 // this macro creates an empty function, which will called by the RegisterAllFunctions()
521 // to let the user the possibility to also register some functions by hand.
522 NOADDITIONAL;
523