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