xref: /trunk/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