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 // Documentation about bootstraping can be found at:
32 // http://udk.openoffice.org/common/man/concept/micro_deployment.html
33 
34 #include <math.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <algorithm> // STL
38 
39 #include "testshl/stringhelper.hxx"
40 
41 #include <testshl/simpleheader.hxx>
42 //#include "stringhelper.hxx"
43 //#include "valueequal.hxx"
44 #include <rtl/bootstrap.hxx>
45 
46 #include <rtl/ustrbuf.hxx>
47 #include <rtl/ustring.h>
48 #include <rtl/ustring.hxx>
49 #include <osl/file.hxx>
50 #include <osl/module.hxx>
51 #include <osl/process.h> /* osl_getExecutableFile() */
52 
53 #include <osl/thread.hxx>
54 
55 // using namespace osl;
56 using namespace rtl;
57 
58 #define TESTSHL2_INI "testshl2"
59 #define PSEUDO_INI   "pseudo"
60 
61 /** print a UNI_CODE String. And also print some comments of the string.
62  */
63 inline void printUString( const ::rtl::OUString & str, const sal_Char * msg = "" )
64 {
65 
66     if (strlen(msg) > 0)
67     {
68         t_print("%s: ", msg );
69     }
70     rtl::OString aString;
71     aString = ::rtl::OUStringToOString( str, RTL_TEXTENCODING_ASCII_US );
72     t_print("%s\n", (char *)aString.getStr( ) );
73 }
74 
75 /** if the file exist
76  */
77 bool t_fileExist(rtl::OUString const& _sFilename)
78 {
79     ::osl::FileBase::RC   nError1;
80     ::osl::File aTestFile( _sFilename );
81     nError1 = aTestFile.open ( OpenFlag_Read );
82     if ( ( ::osl::FileBase::E_NOENT != nError1 ) && ( ::osl::FileBase::E_ACCES != nError1 ) )
83     {
84         aTestFile.close( );
85         return true;
86     }
87     return false;
88 }
89 
90 /** get the exectutable path ( here is bootstrap_process), on Linux, such as "sal/unxlngi4.pro/bin/"
91   */
92 inline ::rtl::OUString getModulePath( void )
93 {
94     ::rtl::OUString suDirPath;
95     ::osl::Module::getUrlFromAddress( ( oslGenericFunction ) &getModulePath, suDirPath );
96 
97     suDirPath = suDirPath.copy( 0, suDirPath.lastIndexOf('/') );
98     suDirPath = suDirPath.copy( 0, suDirPath.lastIndexOf('/') + 1);
99     suDirPath += rtl::OUString::createFromAscii("bin");
100     return suDirPath;
101 }
102 
103 #define TESTSHL2_INI "testshl2"
104 #define PSEUDO_INI   "pseudo"
105 
106 
107 static rtl::OUString getExecutableDirectory()
108 {
109     rtl::OUString fileName;
110     osl_getExecutableFile(&fileName.pData);
111 
112     sal_Int32 nDirEnd = fileName.lastIndexOf('/');
113 
114     OSL_ENSURE(nDirEnd >= 0, "Cannot locate executable directory");
115 
116     rtl::OUString aDirURL = fileName.copy(0, nDirEnd);
117     return aDirURL;
118 }
119 
120 
121 // get the URL of testshl2rc/rtlrc/pseudorc
122 inline rtl::OUString t_getSourcePath(rtl::OString const& _sFilename)
123 {
124 
125      rtl::OUString aDirURL(getExecutableDirectory());
126      aDirURL += OUString::createFromAscii( "/");
127      aDirURL += OUString::createFromAscii( _sFilename.getStr() );
128 #if defined(WNT) || defined(OS2)
129     aDirURL += rtl::OUString::createFromAscii(".ini");
130 #else
131     aDirURL += rtl::OUString::createFromAscii("rc");
132 #endif
133     return aDirURL;
134 
135 // LLA: does not right work on my personal laptop, SRC_ROOT does not show where the source is :-(.
136 /*
137   sal_Char *  pStr = getenv("SRC_ROOT");
138   rtl::OUString suPath;
139   if (filename != "")
140   {
141   suPath = rtl::OUString::createFromAscii(pStr) + rtl::OUString::createFromAscii( "/sal/qa/rtl/bootstrap/" )
142   + rtl::OUString::createFromAscii( filename );
143   }
144   else
145   {
146   suPath = rtl::OUString::createFromAscii(pStr) + rtl::OUString::createFromAscii( "/sal/qa/rtl/bootstrap" );
147   }
148   rtl::OUString suURL;
149   ::osl::FileBase::getFileURLFromSystemPath( suPath, suURL );
150   return suURL;
151 */
152 }
153 
154 void thread_sleep_tenth_sec(sal_Int32 _nTenthSec)
155 {
156 #ifdef WNT      //Windows
157     Sleep(_nTenthSec * 100 );
158 #endif
159 #if ( defined UNX ) || ( defined OS2 )  //Unix
160     TimeValue nTV;
161     nTV.Seconds = static_cast<sal_uInt32>( _nTenthSec/10 );
162     nTV.Nanosec = ( (_nTenthSec%10 ) * 100000000 );
163     osl_waitThread(&nTV);
164 #endif
165 }
166 
167 // -----------------------------------------------------------------------------
168 
169 namespace rtl_Bootstrap
170 {
171     class ctor : public CppUnit::TestFixture
172     {
173     public:
174         // initialise your test code values here.
175         void setUp()
176             {
177             }
178 
179         void tearDown()
180             {
181             }
182 
183         // ctor with ini name
184         void ctor_001()
185             {
186                 rtl::OUString suIniname = t_getSourcePath(TESTSHL2_INI);
187                 printUString( suIniname );
188                 Bootstrap aBootstrap( suIniname );
189                 rtl::OUString suGetname; // = rtl::OUString::createFromAscii("");
190                 aBootstrap.getIniName( suGetname );
191                 printUString( suGetname );
192 
193                 // LLA: first: this seems to be a wrong test.
194                 //      second: there seems to be a design hole, if I give a absolute path ini file,
195                 //              but try to use ${file::KEYVALUE} than 'file' will only used out of the 'executable path'/file
196                 //              not from the path given from the absolute path.
197 
198                 // Due to the fact, we create at this position a file (createTestshl2rc() ), we check for existance
199                 bool bFileExist = t_fileExist( suGetname );
200                 CPPUNIT_ASSERT_MESSAGE("ctor error with initial file.", bFileExist == true );
201             }
202 
203         void ctor_002()
204             {
205                 rtl::Bootstrap aBootstrap;
206                 rtl::OUString suGetname;
207                 aBootstrap.getIniName( suGetname );
208                 printUString( suGetname );
209                 CPPUNIT_ASSERT_MESSAGE("ctor error without initial file.", suGetname.getLength() != 0 );
210             }
211 
212         CPPUNIT_TEST_SUITE(ctor);
213         CPPUNIT_TEST(ctor_001);
214         CPPUNIT_TEST(ctor_002);
215         CPPUNIT_TEST_SUITE_END();
216     }; // class ctor
217 
218     class getFrom : public CppUnit::TestFixture
219     {
220     public:
221         // initialise your test code values here.
222         void setUp()
223             {
224             }
225 
226         void tearDown()
227             {
228             }
229         // get the value of env variable
230         void getFrom_001()
231             {
232                 Bootstrap aBootstrap;
233                 rtl::OUString suValue;
234                 rtl::OUString suValuename = rtl::OUString::createFromAscii( "SOLAR_JAVA" );
235                 //aBootstrap.getFrom( suValuename, suValue );
236                 aBootstrap.getFrom( suValuename, suValue );
237                 sal_Char *  pStr = getenv("SOLAR_JAVA");
238                 //      printUString( suGetname );
239                 CPPUNIT_ASSERT_MESSAGE("get the value of environment variable.", suValue.compareToAscii( pStr ) == 0 );
240             }
241         /* Notes on Windows:
242            void getFrom_001_1()
243            {
244            Bootstrap aBootstrap;
245            rtl::OUString suValue;
246            rtl::OUString suValuename = rtl::OUString::createFromAscii( "SRC_ROOT" );
247            //aBootstrap.getFrom( suValuename, suValue );
248            aBootstrap.getFrom( suValuename, suValue );
249            sal_Char *  pStr = getenv("SRC_ROOT");
250            //   printUString( suGetname );
251            CPPUNIT_ASSERT_MESSAGE("get the value of environment variable.", suValue.compareToAscii( pStr ) == 0 );
252            }
253            The result on Windows:
254            # # the SRC_ROOT is e:\Qadev\cvs\m19
255            # # suValue is e:Qadevcvsm19
256            reason:
257            The problem is that the internally getenv()ed variable SRC_ROOT is macro expanded,
258            thus every \ will introduce an escape.
259         */
260 
261         // get the value of a variable in ini file
262         void getFrom_002()
263             {
264                 rtl::OUString suIniname = t_getSourcePath(TESTSHL2_INI);
265                 Bootstrap aBootstrap( suIniname );
266                 rtl::OUString suGetname;
267                 rtl::OUString suValuename = rtl::OUString::createFromAscii( "INHERITED_VALUE" );
268                 aBootstrap.getFrom( suValuename, suGetname );
269                 printUString( suGetname );
270                 CPPUNIT_ASSERT_MESSAGE("get the value of a variable in ini file.", suGetname.getLength() != 0 );
271             }
272 
273         //use defaut value
274         void getFrom_003()
275             {
276                 rtl::OUString suIniname = t_getSourcePath(TESTSHL2_INI);
277                 Bootstrap aBootstrap( suIniname );
278                 rtl::OUString suGetname;
279                 rtl::OUString suValuename = rtl::OUString::createFromAscii( "MY_VALUE" );
280                 rtl::OUString myDefault = rtl::OUString::createFromAscii( "2" );
281                 aBootstrap.getFrom( suValuename, suGetname, myDefault );
282                 //printUString( suGetname );
283                 CPPUNIT_ASSERT_MESSAGE("getFrom use default.", suGetname.compareTo( myDefault ) == 0 );
284             }
285 
286         void getFrom_004()
287             {
288                 t_print("1\n");
289                 // initialise Bootstrap with an own ini file
290                 // PSEUDO_INI is pseudo(rc|.ini) created be create_pseudorc()
291                 rtl::OUString suIniname = t_getSourcePath(PSEUDO_INI);
292                 Bootstrap aBootstrap( suIniname );
293 
294                 rtl::OUString suGetIniName;
295                 aBootstrap.getIniName( suGetIniName );
296 
297                 printUString(suGetIniName, "Current bootstrap file");
298                 sal_Int32 nIndex = suGetIniName.indexOf(rtl::OUString::createFromAscii( "pseudo" ));
299                 CPPUNIT_ASSERT_MESSAGE("ini name must have 'pseudo' in name.", nIndex > 0);
300 
301                 // rtlBootstrapHandle bsHandle = aBootstrap.getHandle();
302                 // CPPUNIT_ASSERT_MESSAGE("getHandle return NULL!", bsHandle != 0);
303 
304                 rtl::OUString suValue;
305                 rtl::OUString suKeyName = rtl::OUString::createFromAscii( "FILE" );
306                 aBootstrap.getFrom( suKeyName, suValue );
307                 printUString( suValue );
308                 sal_Int32 nCompare = suValue.compareTo( rtl::OUString::createFromAscii("pseudo file") );
309 
310                 CPPUNIT_ASSERT_MESSAGE("<Bootstrap('pseudo')>.getFrom('FILE', ...) result is unexpected.",  nCompare == 0);
311             }
312         void getFrom_004_1()
313             {
314                 // get the same key out of the default context
315                 rtl::OUString suKeyName = rtl::OUString::createFromAscii( "FILE" );
316                 rtl::OUString suGetValue;
317                 Bootstrap::get( suKeyName, suGetValue );
318                 printUString( suGetValue );
319 
320                 CPPUNIT_ASSERT_MESSAGE("Bootstrap::get('FILE', ...)", suGetValue.compareTo( rtl::OUString::createFromAscii("testshl2 file") ) == 0 );
321             }
322 
323 	/** helper function: return the child process's ret value( typedef sal_uInt32 oslProcessExitCode;)
324 	   * param1 is the process's name(only file name, not include path)
325 	  */
326 	 oslProcessExitCode ini_execProcess( const sal_Char* process_name, const sal_Char * flag )
327 	 {
328 	 	rtl::OUString suCWD = getModulePath();
329     		oslProcess hProcess = NULL;
330    		rtl::OUString suFileURL = suCWD;
331         	suFileURL += rtl::OUString::createFromAscii("/") +  rtl::OUString::createFromAscii(process_name) ;
332 #if defined(WNT) || defined(OS2)
333 		suFileURL += rtl::OUString::createFromAscii(".exe");
334 #endif
335         	const int nParameterCount = 3;
336     		rtl_uString* pParameters[ nParameterCount ];
337     		OUString suFlag( OUString::createFromAscii(flag) );
338 		OUString suEnv1( OUString::createFromAscii("-env:UNO_SERVICES=service.rdb"));
339 		OUString suIniname = t_getSourcePath("rtl");
340 		printUString( suIniname, "rtl path:");
341 		//OUString suEnv2( OUString::createFromAscii("-env:MYENV=bootstrap_process"));
342 
343         	pParameters[0] = suFlag.pData;
344         	pParameters[1] = suEnv1.pData;
345         	// the custom ini/rc file's URL
346         	pParameters[2] = suIniname.pData;
347 
348         	oslProcessError osl_error = osl_executeProcess(
349         	    suFileURL.pData,
350         	    pParameters,
351             	    nParameterCount,
352         	    osl_Process_WAIT,
353         	    0,
354         	    suCWD.pData,
355         	    NULL,
356         	    0,
357         	    &hProcess );
358 
359         	CPPUNIT_ASSERT_MESSAGE
360         	(
361         	    "osl_createProcess failed",
362         	    osl_error == osl_Process_E_None
363         	);
364 	       	osl_joinProcess(hProcess);
365         	oslProcessInfo* pInfo = new oslProcessInfo;
366 		pInfo->Size = sizeof( oslProcessInfo );
367 		osl_error = osl_getProcessInfo( hProcess, osl_Process_EXITCODE, pInfo );
368 		CPPUNIT_ASSERT_MESSAGE
369         	(
370         	    "osl_getProcessInfo returned with failure",
371         	    osl_Process_E_None == osl_error
372         	);
373 
374 		t_print("the exit code is %d.\n", pInfo->Code );
375 		oslProcessExitCode nCode = pInfo->Code;
376 		delete pInfo;
377 	 	return nCode;
378 	}
379 
380          void getFrom_005_1()
381             {
382 	       	oslProcessExitCode nExitCode = ini_execProcess( "bootstrap_process", "1" );
383         	CPPUNIT_ASSERT_MESSAGE("Parameters passed by command line can not be gotten!",
384 				nExitCode == 10 );
385 	    }
386 	 void getFrom_005_2()
387             {
388 	       	oslProcessExitCode nExitCode = ini_execProcess( "bootstrap_process", "2" );
389         	CPPUNIT_ASSERT_MESSAGE("Parameters passed by .ini/rc file can not be gotten!",
390 				nExitCode == 20 );
391 	    }
392 	 void getFrom_005_3()
393             {
394 #if (defined WNT) || (defined SOLARIS)
395 		putenv(const_cast< char * >("QADEV_BOOTSTRAP=sun&ms"));
396 #else
397             	setenv("QADEV_BOOTSTRAP", "sun&ms", 0);
398 #endif
399 	       	oslProcessExitCode nExitCode = ini_execProcess( "bootstrap_process", "3" );
400         	CPPUNIT_ASSERT_MESSAGE("Parameters passed by environment variables can not be gotten!",
401 				nExitCode == 30 );
402 	    }
403 	void getFrom_005_4()
404             {
405             	oslProcessExitCode nExitCode = ini_execProcess( "bootstrap_process", "4" );
406         	CPPUNIT_ASSERT_MESSAGE("Parameters passed by customed .ini/rc file can not be gotten!",
407 				nExitCode == 40 );
408 	    }
409 	void getFrom_005_5()
410             {
411             	oslProcessExitCode nExitCode = ini_execProcess( "bootstrap_process", "5" );
412         	CPPUNIT_ASSERT_MESSAGE("Parameters passed by inheritance can not be gotten!",
413 				nExitCode == 50 );
414 	    }
415 	void getFrom_005_6()
416             {
417             	oslProcessExitCode nExitCode = ini_execProcess( "bootstrap_process", "6" );
418         	CPPUNIT_ASSERT_MESSAGE("Parameters passed by default can not be gotten!",
419 				nExitCode == 60 );
420 	    }
421 
422         CPPUNIT_TEST_SUITE(getFrom);
423         CPPUNIT_TEST(getFrom_001);
424         CPPUNIT_TEST(getFrom_002);
425         CPPUNIT_TEST(getFrom_003);
426         CPPUNIT_TEST(getFrom_004);
427         CPPUNIT_TEST(getFrom_004_1);
428         CPPUNIT_TEST(getFrom_005_1);
429         CPPUNIT_TEST(getFrom_005_2);
430         CPPUNIT_TEST(getFrom_005_3);
431         CPPUNIT_TEST(getFrom_005_4);
432         CPPUNIT_TEST(getFrom_005_5);
433         CPPUNIT_TEST(getFrom_005_6);
434         CPPUNIT_TEST_SUITE_END();
435     }; // class getFrom
436 
437     class setIniFilename : public CppUnit::TestFixture
438     {
439     public:
440         // initialise your test code values here.
441         void setUp()
442             {
443             }
444 
445         void tearDown()
446             {
447             }
448 
449         void setIniFilename_001()
450             {
451                 Bootstrap aBootstrap;
452 
453                 rtl::OUString suGetIniname;
454                 aBootstrap.getIniName( suGetIniname );
455                 //which should be .....testshl2rc
456                 //printUString( suGetIniname );
457 
458                 rtl::OUString suIniname = t_getSourcePath(PSEUDO_INI);
459                 Bootstrap::setIniFilename( suIniname );
460 
461                 rtl::OUString suGetname;
462                 aBootstrap.getIniName( suGetname );
463 
464                 printUString( suGetname );
465                 CPPUNIT_ASSERT_MESSAGE("setIniFilename then get it.", suGetname.compareTo( suIniname ) == 0
466                                        && suGetname.compareTo( suGetIniname ) != 0 );
467             }
468 
469         void setIniFilename_002()
470             {
471                 rtl::OUString suIniname = t_getSourcePath(TESTSHL2_INI);
472                 // CPPUNIT_ASSERT_MESSAGE("test failed, Bootstrap ini does not exist.", t_fileExist(suIniname ) == true);
473 
474                 Bootstrap::setIniFilename( suIniname );
475                 //rtl_bootstrap_args_open( suIniname.pData );
476                 rtl::OUString suGetname;
477                 rtl::OUString suValuename = rtl::OUString::createFromAscii( "INHERITED_VALUE" );
478                 //aBootstrap.getFrom( suValuename, suGetname  );
479                 Bootstrap::get( suValuename, suGetname  );
480                 printUString( suGetname );
481                 CPPUNIT_ASSERT_MESSAGE("setIniFilename and get value of the argument.", suGetname.getLength() != 0 );
482             }
483 
484         CPPUNIT_TEST_SUITE(setIniFilename);
485         CPPUNIT_TEST(setIniFilename_001);
486         CPPUNIT_TEST(setIniFilename_002);
487         CPPUNIT_TEST_SUITE_END();
488     }; // class setIniFilename
489 
490     class getHandle : public CppUnit::TestFixture
491     {
492     public:
493         // initialise your test code values here.
494         void setUp()
495             {
496             }
497 
498         void tearDown()
499             {
500             }
501 
502         void getHandle_001()
503             {
504                 rtl::OUString suIniname = t_getSourcePath(TESTSHL2_INI);
505                 Bootstrap aBootstrap;
506                 rtlBootstrapHandle bsHandle = aBootstrap.getHandle();
507                 CPPUNIT_ASSERT_MESSAGE("getHandle should return 0 if the bootstrap has no ini file!", bsHandle == 0 );
508             }
509         void getHandle_002()
510             {
511                 rtl::OUString suIniname = t_getSourcePath(PSEUDO_INI);
512                 Bootstrap aBootstrap( suIniname );
513 
514                 rtlBootstrapHandle bsHandle = aBootstrap.getHandle();
515                 CPPUNIT_ASSERT_MESSAGE("getHandle return NULL!", bsHandle != 0);
516 
517                 //rtl::OUString iniName;
518                 //rtl_bootstrap_get_iniName_from_handle( bsHandle, &iniName.pData );
519 
520                 rtl::OUString suValue;
521                 rtl::OUString suKeyName = rtl::OUString::createFromAscii( "PSEUDOFILE" );
522                 rtl_bootstrap_get_from_handle(bsHandle, suKeyName.pData, &suValue.pData, NULL);
523                 printUString( suValue);
524 
525                 CPPUNIT_ASSERT_MESSAGE("Can not use the handle which is returned by getHandle!", suValue.equals( rtl::OUString::createFromAscii("be pseudo") ) == sal_True );
526 
527                 // CPPUNIT_ASSERT_MESSAGE("Can not use the handle which is returned by getHandle!",
528                 //      suGetname.equalsIgnoreAsciiCase( iniName ) == sal_True );
529             }
530 
531         CPPUNIT_TEST_SUITE(getHandle);
532         CPPUNIT_TEST(getHandle_001);
533         CPPUNIT_TEST(getHandle_002);
534         CPPUNIT_TEST_SUITE_END();
535     }; // class getHandle
536 
537     class set : public CppUnit::TestFixture
538     {
539     public:
540         // initialise your test code values here.
541         void setUp()
542             {
543             }
544 
545         void tearDown()
546             {
547             }
548 
549         void set_001()
550             {
551                 //in ini fle, INHERITED_VALUE=inherited_value
552                 rtl::OUString suIniname = t_getSourcePath(TESTSHL2_INI);
553                 Bootstrap aBootstrap( suIniname);
554                 rtl::OUString suName = rtl::OUString::createFromAscii( "INHERITED_VALUE" );
555                 rtl::OUString suValue = rtl::OUString::createFromAscii( "ok" );
556                 // set to another value
557                 Bootstrap::set( suName, suValue );
558                 rtl::OUString suGetValue;
559                 Bootstrap::get( suName, suGetValue);
560                 CPPUNIT_ASSERT_MESSAGE("set and get argument failed.", suGetValue.compareTo(suValue) == 0 );
561             }
562         void set_002()
563             {
564                 rtl::OUString suIniname = t_getSourcePath(TESTSHL2_INI);
565                 Bootstrap myBootstrap( suIniname);
566                 rtl::OUString suName = rtl::OUString::createFromAscii( "INHERITED_VALUE" );
567                 rtl::OUString suGetOrientValue;
568                 Bootstrap::get( suName, suGetOrientValue);
569                 // ??  INHERITED_VALUE = ok now, which is set in set_001
570                 printUString( suGetOrientValue );
571 
572                 rtl::OUString suValue = rtl::OUString::createFromAscii( TESTSHL2_INI );
573                 // set to another value
574                 Bootstrap::set( suName, suValue );
575                 rtl::OUString suGetValue;
576                 Bootstrap::get( suName, suGetValue);
577                 CPPUNIT_ASSERT_MESSAGE("set and get argument failed.", suGetValue.compareTo(suValue) == 0 );
578             }
579 
580         CPPUNIT_TEST_SUITE(set);
581         CPPUNIT_TEST(set_001);
582         CPPUNIT_TEST(set_002);
583         CPPUNIT_TEST_SUITE_END();
584     }; // class set
585 
586     class expandMacrosFrom : public CppUnit::TestFixture
587     {
588     public:
589         void setUp()
590             {
591             }
592 
593         void tearDown()
594             {
595             }
596         void expandMacrosFrom_001()
597             {
598                 rtl::OUString suIniname = t_getSourcePath(TESTSHL2_INI);
599                 Bootstrap aBootstrap( suIniname);
600                 rtl::OUString suMacro = rtl::OUString::createFromAscii( "$MYVAR/expand1" );
601                 //printUString( suMacro );
602                 //expandMacro now
603                 aBootstrap.expandMacrosFrom( suMacro );
604                 rtl::OUString suExpectedMacro = rtl::OUString::createFromAscii( "src680_test/expand1" );
605                 //printUString( suMacro );
606                 CPPUNIT_ASSERT_MESSAGE("expandMacrosFrom failed.", suMacro.compareTo(suExpectedMacro) == 0 );
607             }
608 
609         /** here a special macro should expand
610           * if rtlrc is under sal/qa/rtl/bootstrap/, "${rtlrc:Bootstrap:RTLVALUE}" could be expanded
611           * else rtlrc is under solver/680/unxlngi4.pro/bin/, "${file:/// ....solver/680/unxlngi4.pro/bin/rtlrc:Bootstrap:RTLVALUE}"
612 	  * could not be expanded
613 	  */
614         void expandMacrosFrom_002()
615             {
616                 // Build a string with '${rtl.ini:RTLVALUE}' and try to expand it.
617                 // In function 'create_rtlrc() is the content of the rtl.ini file.
618 
619                 rtl::OUString suIniname = t_getSourcePath(TESTSHL2_INI);
620                 t_print("inifile is:");
621     	        printUString( suIniname );
622                 Bootstrap aBootstrap( suIniname) ;
623               	rtl::OUString suMacro = rtl::OUString::createFromAscii( "${" );         //rtlrc:Bootstrap:RTLVALUE}");
624 
625      rtl::OUString aDirURL = OUString::createFromAscii( "$ORIGIN");
626      aDirURL += OUString::createFromAscii( "/");
627      aDirURL += OUString::createFromAscii( "rtl" );
628 #if defined(WNT) || defined(OS2)
629     aDirURL += rtl::OUString::createFromAscii(".ini");
630 #else
631     aDirURL += rtl::OUString::createFromAscii("rc");
632 #endif
633 
634                 suMacro += aDirURL;//t_getSourcePath("rtl");
635     	        suMacro += rtl::OUString::createFromAscii( "::RTLVALUE}");
636 
637                 t_print("created macro is: ");
638     	        printUString( suMacro );
639                 //expandMacro now
640                 aBootstrap.expandMacrosFrom( suMacro );
641                 t_print("expanded macro is:");
642                 printUString( suMacro );
643                 rtl::OUString suExpectedMacro = rtl::OUString::createFromAscii( "qadev17" );
644                 CPPUNIT_ASSERT_MESSAGE("failed, can't expand '${file:///.../" SAL_CONFIGFILE("rtl") "::RTLVALUE}' to 'qadev17'", suMacro.compareTo(suExpectedMacro) == 0 );
645             }
646         void expandMacrosFrom_002_1()
647             {
648                 rtl::OUString suIniname = t_getSourcePath(TESTSHL2_INI);
649                 t_print("inifile is:");
650     	        printUString( suIniname );
651                 Bootstrap aBootstrap( suIniname);
652 
653                 rtl::OUString suMacro;
654                 // just a simple test, if this really work.
655                 aBootstrap.getFrom(rtl::OUString::createFromAscii( "SOFROMVALUE2" ), suMacro );
656                 t_print("SOFROMVALUE2:");
657                 printUString( suMacro );
658                 CPPUNIT_ASSERT_MESSAGE("'SOFROMVALUE2' seems to do not exist.", suMacro.getLength() > 0 );
659 
660                 aBootstrap.getFrom(rtl::OUString::createFromAscii( "SOFROMVALUE" ), suMacro );
661 
662                 t_print("SOFROMVALUE:");
663     	        printUString( suMacro );
664 
665                 //expandMacro now
666                 // seems to be, that getFrom() already expand the string
667                 // t_print("expanded macro is:");
668                 // aBootstrap.expandMacrosFrom( suMacro );
669                 // printUString( suMacro );
670                 rtl::OUString suExpectedMacro = rtl::OUString::createFromAscii( "src680_qadev" );
671                 CPPUNIT_ASSERT_MESSAGE("failed, can't expand '${" SAL_CONFIGFILE("rtl") "::SOVALUE}' to 'src680_qadev'", suMacro.compareTo(suExpectedMacro) == 0 );
672             }
673         void expandMacrosFrom_002_2()
674             {
675                 // test, to read and expand SOFROMVALUE3
676                 // SOFROMVALUE3 is 'rtl(.ini|rc)::TESTSHL_SOVALUE' which should expand to 'rtlfile' if all is ok.
677 
678                 rtl::OUString suIniname = t_getSourcePath(TESTSHL2_INI);
679                 t_print("inifile is:");
680     	        printUString( suIniname );
681                 Bootstrap aBootstrap( suIniname);
682 
683                 rtl::OUString suMacro;
684                 aBootstrap.getFrom(rtl::OUString::createFromAscii( "SOFROMVALUE3" ), suMacro );
685 
686                 t_print("SOFROMVALUE3:");
687                 printUString( suMacro );
688 
689                 if (suMacro.equals(rtl::OUString::createFromAscii("testshl2_file") ) == sal_True)
690                 {
691                     CPPUNIT_ASSERT_MESSAGE("Value 'SOFROMVALUE3' is read from the wrong ini file.", 0 );
692                 }
693                 else
694                 {
695                     CPPUNIT_ASSERT_MESSAGE("SOFROMVALUE3 should contain 'rtlfile'.", suMacro.equals(rtl::OUString::createFromAscii("rtlfile") ) == sal_True );
696                 }
697             }
698 //? I don't know if this is a right test.
699 //         void expandMacrosFrom_002_3()
700 //             {
701 //                 // test, to read and expand SOFROMVALUE4
702 //                 // SOFROMVALUE4 is 'rtl(.ini|rc):Other_Section:TESTSHL_SOVALUE' which should expand to '' if all is ok.
703 //
704 //                 rtl::OUString suIniname = t_getSourcePath(TESTSHL2_INI);
705 //                 t_print("inifile is:");
706 //     	        printUString( suIniname );
707 //                 Bootstrap aBootstrap( suIniname);
708 //
709 //                 rtl::OUString suMacro;
710 //                 aBootstrap.getFrom(rtl::OUString::createFromAscii( "SOFROMVALUE4" ), suMacro );
711 //
712 //                 t_print("SOFROMVALUE4:");
713 //                 printUString( suMacro );
714 //
715 //                 if (suMacro.equals(rtl::OUString::createFromAscii("testshl2_file") ) == sal_True)
716 //                 {
717 //                     CPPUNIT_ASSERT_MESSAGE("Value 'SOFROMVALUE4' is read from the wrong section out of the wrong ini file.", 0 );
718 //                 }
719 //                 else if (suMacro.equals(rtl::OUString::createFromAscii("testshl2_file_other") ) == sal_True)
720 //                 {
721 //                     CPPUNIT_ASSERT_MESSAGE("Value 'SOFROMVALUE4' is read from the wrong ini file.", 0 );
722 //                 }
723 //                 else
724 //                 {
725 //                     CPPUNIT_ASSERT_MESSAGE("Value 'SOFROMVALUE4' should contain 'rtlfile_other'.", suMacro.equals(rtl::OUString::createFromAscii("rtlfile_other") ) == sal_True );
726 //                 }
727 //             }
728         void expandMacrosFrom_003()
729             {
730                 rtl::OUString suIniname = t_getSourcePath(TESTSHL2_INI);
731                 Bootstrap aBootstrap( suIniname);
732                 rtl::OUString suMacro[4];
733                 suMacro[0] = rtl::OUString::createFromAscii( "$SYSUSERCONFIG" );
734                 suMacro[1] = rtl::OUString::createFromAscii( "$SYSUSERHOME" );
735                 suMacro[2] = rtl::OUString::createFromAscii( "$SYSBINDIR" );
736                 suMacro[3] = rtl::OUString::createFromAscii( "$ORIGIN" );
737 
738                 for ( int i = 0; i < 4; i++ )
739                 {
740                     aBootstrap.expandMacrosFrom( suMacro[i] );
741                     printUString(suMacro[i]);
742                 }
743                 // printUString( t_getSourcePath("") );
744                 // CPPUNIT_ASSERT_MESSAGE("some integral variables.", suMacro[3].equalsIgnoreAsciiCase(t_getSourcePath("")) == sal_True );
745                 CPPUNIT_ASSERT_MESSAGE("some integral variables.", suMacro[0].getLength() > 0 &&
746                                        suMacro[1].getLength() > 0 &&
747                                        suMacro[2].getLength() > 0 &&
748                                        suMacro[3].getLength() > 0);
749             }
750 
751         void testRecursion() {
752             rtl::OUString t(RTL_CONSTASCII_USTRINGPARAM("$RECURSIVE"));
753             Bootstrap(t_getSourcePath(TESTSHL2_INI)).expandMacrosFrom(t);
754             CPPUNIT_ASSERT_MESSAGE(
755                 "recursion detection",
756                 t.equalsAsciiL(
757                     RTL_CONSTASCII_STRINGPARAM("***RECURSION DETECTED***")));
758         }
759 
760         void testLink() {
761             rtl::OUString t(RTL_CONSTASCII_USTRINGPARAM("$LINKED"));
762             Bootstrap(t_getSourcePath(TESTSHL2_INI)).expandMacrosFrom(t);
763             CPPUNIT_ASSERT_MESSAGE(
764                 "link file",
765                 t.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("qadev17")));
766         }
767 
768         void testOverride() {
769             rtl::OUString t1(
770                 RTL_CONSTASCII_USTRINGPARAM(
771                     "${.override:$ORIGIN/" SAL_CONFIGFILE("rtl") ":ORIGIN}"));
772             Bootstrap(t_getSourcePath("rtl")).expandMacrosFrom(t1);
773             CPPUNIT_ASSERT_MESSAGE(
774                 "override ORIGIN",
775                 t1.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("direct")));
776             rtl::OUString t2(
777                 RTL_CONSTASCII_USTRINGPARAM(
778                     "${.override:$ORIGIN/" SAL_CONFIGFILE("none") ":MYVAR}"));
779             Bootstrap::expandMacros(t2);
780             CPPUNIT_ASSERT_MESSAGE(
781                 "override MYVAR",
782                 t2.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("src680_test")));
783         }
784 
785         void testNonexisting() {
786             rtl::OUString t(
787                 RTL_CONSTASCII_USTRINGPARAM(
788                     "${$ORIGIN/" SAL_CONFIGFILE("none") ":MYVAR}"));
789             Bootstrap::expandMacros(t);
790             CPPUNIT_ASSERT_MESSAGE(
791                 "nonexisting",
792                 t.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("src680_test")));
793         }
794 
795         void testSection() {
796             rtl::OUStringBuffer b;
797             b.appendAscii(RTL_CONSTASCII_STRINGPARAM("${"));
798             rtl::OUString p(t_getSourcePath(TESTSHL2_INI));
799             for (sal_Int32 i = 0; i < p.getLength(); ++i) {
800                 if (p[i] != 'u') {
801                     b.append(static_cast< sal_Unicode >('\\'));
802                 }
803                 b.append(p[i]);
804             }
805             b.appendAscii(RTL_CONSTASCII_STRINGPARAM(":Other_Section:EXPAND}"));
806             rtl::OUString t(b.makeStringAndClear());
807             Bootstrap(t_getSourcePath(TESTSHL2_INI)).expandMacrosFrom(t);
808             CPPUNIT_ASSERT_MESSAGE(
809                 "section expansion",
810                 t.equalsAsciiL(
811                     RTL_CONSTASCII_STRINGPARAM("$FILE")));
812                 // the correct answer would be "testshl2 file" instead, but
813                 // expansion including a section currently erroneously does not
814                 // recursively expand macros in the resulting replacement text
815         }
816 
817         CPPUNIT_TEST_SUITE(expandMacrosFrom);
818         CPPUNIT_TEST(expandMacrosFrom_001);
819         CPPUNIT_TEST(expandMacrosFrom_002);
820         CPPUNIT_TEST(expandMacrosFrom_002_1);
821         CPPUNIT_TEST(expandMacrosFrom_002_2);
822 //?        CPPUNIT_TEST(expandMacrosFrom_002_3);
823         CPPUNIT_TEST(expandMacrosFrom_003);
824         CPPUNIT_TEST(testRecursion);
825         CPPUNIT_TEST(testLink);
826         CPPUNIT_TEST(testOverride);
827         CPPUNIT_TEST(testNonexisting);
828         CPPUNIT_TEST(testSection);
829         CPPUNIT_TEST_SUITE_END();
830     }; // class expandMacrosFrom
831 
832     class expandMacros : public CppUnit::TestFixture
833     {
834     public:
835         // initialise your test code values here.
836         void setUp()
837             {
838             }
839 
840         void tearDown()
841             {
842             }
843 
844         void expandMacros_001()
845             {
846                 rtl::OUString suIniname = t_getSourcePath(TESTSHL2_INI);
847                 Bootstrap aBootstrap( suIniname) ;
848                 rtl::OUString suMacro = rtl::OUString::createFromAscii( "$INHERITED_VALUE/well" );
849                 Bootstrap::expandMacros( suMacro );
850 
851 		rtl::OUString suName = rtl::OUString::createFromAscii( "INHERITED_VALUE" );
852                 OUString suGetValue;
853                 Bootstrap::get( suName, suGetValue );
854                 suGetValue += OUString::createFromAscii( "/well" );
855                 CPPUNIT_ASSERT_MESSAGE("expandMacros failed.", suGetValue.compareTo(suMacro) == 0 );
856             }
857 
858         CPPUNIT_TEST_SUITE(expandMacros);
859         CPPUNIT_TEST(expandMacros_001);
860         //  CPPUNIT_TEST(expandMacros_002);
861         CPPUNIT_TEST_SUITE_END();
862     }; // class expandMacros
863 
864     CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(rtl_Bootstrap::ctor, "rtl_Bootstrap");
865     CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(rtl_Bootstrap::getFrom, "rtl_Bootstrap");
866     CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(rtl_Bootstrap::setIniFilename, "rtl_Bootstrap");
867     CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(rtl_Bootstrap::getHandle, "rtl_Bootstrap");
868     CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(rtl_Bootstrap::set, "rtl_Bootstrap");
869     CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(rtl_Bootstrap::expandMacrosFrom, "rtl_Bootstrap");
870     CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(rtl_Bootstrap::expandMacros, "rtl_Bootstrap");
871 
872 } // namespace rtl_Bootstrap
873 
874 // -----------------------------------------------------------------------------
875 
876 // this macro creates an empty function, which will called by the RegisterAllFunctions()
877 // to let the user the possibility to also register some functions by hand.
878 // NOADDITIONAL;
879 
880 
881 // Here are some helpers, which create a new file 'rtlrc' at the executable path position
882 // and fill the file with some information.
883 // static rtl::OUString getExecutableDirectory()
884 // {
885 //     rtl::OUString fileName;
886 //     osl_getExecutableFile(&fileName.pData);
887 //
888 //     sal_Int32 nDirEnd = fileName.lastIndexOf('/');
889 //
890 //     OSL_ENSURE(nDirEnd >= 0, "Cannot locate executable directory");
891 //
892 //     rtl::OUString aDirURL = fileName.copy(0, nDirEnd);
893 //     return aDirURL;
894 // }
895 
896 static void removeAndCreateFile(rtl::OUString const& _suFileURL, rtl::OString const& _sContent)
897 {
898     osl::File::remove(_suFileURL);
899 
900     ::std::auto_ptr<osl::File> pFile( new osl::File( _suFileURL ) );
901     ::osl::FileBase::RC nError = pFile->open( OpenFlag_Write | OpenFlag_Create );
902     if ( ::osl::FileBase::E_None == nError || ::osl::FileBase::E_EXIST == nError )
903     {
904         t_print(T_VERBOSE, "%s\n" , OString(_suFileURL, _suFileURL.getLength(), RTL_TEXTENCODING_ASCII_US).getStr());
905         sal_uInt64 nWritenBytes;
906         pFile->write(_sContent.getStr(), _sContent.getLength(), nWritenBytes);
907         // t_print("nBytes: %ld\n", nBytes);
908 
909         rtl::OString sError = "can't write enough bytes to file";
910         sError += OString(_suFileURL, _suFileURL.getLength(), RTL_TEXTENCODING_ASCII_US);
911         OSL_ENSURE(nWritenBytes == _sContent.getLength(), sError.getStr());
912 
913         pFile->close();
914     }
915     else
916     {
917         rtl::OString sError = "can't create file URL: '";
918         rtl::OString sFile;
919         sFile <<= _suFileURL;
920         sError += sFile;
921         sError += "' maybe no write access. If it is true with no write access, please create a local environment and start these tests again. rtl::Bootstrap test must quit.";
922         t_print("%s\n", sError.getStr() );
923         exit(1);
924     }
925     OSL_ASSERT(t_fileExist(_suFileURL) == true);
926 }
927 
928 // -----------------------------------------------------------------------------
929 static void create_rtlrc()
930 {
931     rtl::OUString aFileURL(getExecutableDirectory());
932 #if defined(WNT) || defined(OS2)
933     aFileURL += rtl::OUString::createFromAscii("/rtl.ini");
934 #else
935     aFileURL += rtl::OUString::createFromAscii("/rtlrc");
936 #endif
937 
938     rtl::OString sLines;
939     sLines += "[Bootstrap]\n";
940     sLines += "SOVALUE=src680_qadev\n";
941     sLines += "RTLVALUE=qadev17\n";
942     sLines += "TESTSHL_SOVALUE=rtlfile\n";
943     sLines += "RECURSIVE=${$ORIGIN/" SAL_CONFIGFILE("testshl2") ":RECURSIVE}\n";
944     sLines += "ORIGIN=direct\n";
945     sLines += "[Other_Section]\n";
946     sLines += "TESTSHL_SOVALUE=rtlfile_other\n";
947 
948     removeAndCreateFile(aFileURL, sLines);
949 }
950 
951 // -----------------------------------------------------------------------------
952 static void create_testshl2rc()
953 {
954     rtl::OUString aFileURL(getExecutableDirectory());
955 #if defined(WNT) || defined(OS2)
956     aFileURL += rtl::OUString::createFromAscii("/testshl2.ini");
957 #else
958     aFileURL += rtl::OUString::createFromAscii("/testshl2rc");
959 #endif
960     rtl::OString sLines;
961     sLines += "[Bootstrap]\n";
962     sLines += "FILE=testshl2 file\n";
963     sLines += "MYBOOTSTRAPTESTVALUE=file\n";
964     sLines += "INHERITED_VALUE=inherited_value\n";
965     sLines += "INHERITED_OVERWRITTEN_VALUE=not_overwritten\n";
966     sLines += "MYVAR=src680_test\n";
967     sLines += "SOFROMVALUE=${$ORIGIN/" SAL_CONFIGFILE("rtl") "::SOVALUE}\n";
968     sLines += "SOFROMVALUE2=test\n";
969     sLines += "SOFROMVALUE3=${$ORIGIN/" SAL_CONFIGFILE("rtl") "::TESTSHL_SOVALUE}\n";
970     sLines += "TESTSHL_SOVALUE=testshl2_file\n";
971     //? sLines += "SOFROMVALUE4=${" SAL_CONFIGFILE("rtl") ":Other_Section:TESTSHL_SOVALUE}\n";
972     sLines += "ILLEGAL VALUE=test\n";
973     sLines += "ILLEGAL.DOT=test\n";
974     sLines += "ILLEGAL;SEMICOLON=test\n";
975     sLines += "ILLEGAL:COLON=test\n";
976     sLines += "  KEY_FOR_TRIM_TEST  =   value for trim test    \n";
977     sLines += "RECURSIVE=${$ORIGIN/" SAL_CONFIGFILE("rtl") ":RECURSIVE}\n";
978     sLines += "LINKED=${${.link:$ORIGIN/testshl2-link}:RTLVALUE}\n";
979     sLines += "[Other_Section]\n";
980     sLines += "FILE=testshl2 file other\n";
981     sLines += "EXPAND=$FILE\n";
982     //? sLines += "TESTSHL_SOVALUE=testshl2_file_other\n";
983 
984     removeAndCreateFile(aFileURL, sLines);
985 
986     removeAndCreateFile(
987         (getExecutableDirectory() +
988          rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/testshl2-link"))),
989         SAL_CONFIGFILE("rtl"));
990 }
991 
992 // -----------------------------------------------------------------------------
993 
994 static void create_pseudorc()
995 {
996     rtl::OUString aFileURL(getExecutableDirectory());
997 #if defined(WNT) || defined(OS2)
998     aFileURL += rtl::OUString::createFromAscii("/pseudo.ini");
999 #else
1000     aFileURL += rtl::OUString::createFromAscii("/pseudorc");
1001 #endif
1002     rtl::OString sLines;
1003     sLines += "[Bootstrap]\n";
1004     sLines += "FILE=pseudo file\n";
1005     sLines += "PSEUDOFILE=be pseudo\n";
1006 
1007     removeAndCreateFile(aFileURL, sLines);
1008 }
1009 
1010 // -----------------------------------------------------------------------------
1011 void create_bootstrap_processrc()
1012 {
1013     rtl::OUString aDirURL(getModulePath());
1014 #if defined(WNT) || defined(OS2)
1015     aDirURL += rtl::OUString::createFromAscii("/bootstrap_process.ini");
1016 #else
1017     aDirURL += rtl::OUString::createFromAscii("/bootstrap_processrc");
1018 #endif
1019     rtl::OString sLines;
1020     sLines += "[Bootstrap]\n";
1021     sLines += "EXECUTABLE_RC=true\n";
1022     sLines += "IF_CUSTOM_RC=false\n";
1023 
1024     removeAndCreateFile(aDirURL, sLines);
1025 }
1026 // -----------------------------------------------------------------------------
1027 
1028 void RegisterAdditionalFunctions(FktRegFuncPtr _pFunc)
1029 {
1030     (void) _pFunc;
1031     // start message
1032     t_print(T_VERBOSE, "Initializing ...\n" );
1033     create_rtlrc();
1034     create_testshl2rc();
1035     create_pseudorc();
1036     create_bootstrap_processrc();
1037 
1038     t_print(T_VERBOSE, "Initialization Done.\n" );
1039 }
1040 
1041