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