merge the formfield patch from ooo-build
[ooovba.git] / sal / qa / osl / process / osl_process.cxx
blobfd6e58c5a0ace0d3f784763a206ce1fdb8b242a7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: osl_process.cxx,v $
10 * $Revision: 1.10 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sal.hxx"
34 #include <cppunit/simpleheader.hxx>
35 #include <osl/process.h>
36 #include <osl/file.hxx>
37 #include <osl/thread.h>
38 #include <rtl/ustring.hxx>
39 #include <unistd.h>
40 #include <signal.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <osl/module.hxx>
46 #if ( defined WNT ) // Windows
47 #include <tools/prewin.h>
48 # define WIN32_LEAN_AND_MEAN
49 // # include <windows.h>
50 # include <tchar.h>
51 #include <tools/postwin.h>
52 #endif
54 #include "rtl/allocator.hxx"
56 #include <iostream>
57 #include <fstream>
58 #include <vector>
59 #include <algorithm>
60 #include <iterator>
61 #include <string>
63 #if defined(WNT) || defined(OS2)
64 const rtl::OUString EXECUTABLE_NAME = rtl::OUString::createFromAscii("osl_process_child.exe");
65 #else
66 const rtl::OUString EXECUTABLE_NAME = rtl::OUString::createFromAscii("osl_process_child");
67 #endif
70 //########################################
71 std::string OUString_to_std_string(const rtl::OUString& oustr)
73 rtl::OString ostr = rtl::OUStringToOString(oustr, osl_getThreadTextEncoding());
74 return std::string(ostr.getStr());
77 //########################################
78 using namespace osl;
79 using namespace rtl;
81 /** print a UNI_CODE String.
83 inline void printUString( const ::rtl::OUString & str )
85 rtl::OString aString;
87 t_print("#printUString_u# " );
88 aString = ::rtl::OUStringToOString( str, RTL_TEXTENCODING_ASCII_US );
89 t_print("%s\n", aString.getStr( ) );
92 /** get binary Path.
94 inline ::rtl::OUString getExecutablePath( void )
96 ::rtl::OUString dirPath;
97 osl::Module::getUrlFromAddress( ( void* ) &getExecutablePath, dirPath );
98 dirPath = dirPath.copy( 0, dirPath.lastIndexOf('/') );
99 dirPath = dirPath.copy( 0, dirPath.lastIndexOf('/') + 1);
100 dirPath += rtl::OUString::createFromAscii("bin");
101 return dirPath;
104 //rtl::OUString CWD = getExecutablePath();
106 //########################################
107 class Test_osl_joinProcess : public CppUnit::TestFixture
109 const OUString join_param_;
110 const OUString wait_time_;
111 OUString suCWD;
112 OUString suExecutableFileURL;
114 rtl_uString* parameters_[2];
115 int parameters_count_;
117 public:
119 Test_osl_joinProcess() :
120 join_param_(OUString::createFromAscii("-join")),
121 wait_time_(OUString::createFromAscii("1")),
122 parameters_count_(2)
124 parameters_[0] = join_param_.pData;
125 parameters_[1] = wait_time_.pData;
126 suCWD = getExecutablePath();
127 suExecutableFileURL = suCWD;
128 suExecutableFileURL += rtl::OUString::createFromAscii("/");
129 suExecutableFileURL += EXECUTABLE_NAME;
132 /*-------------------------------------
133 Start a process and join with this
134 process specify a timeout so that
135 osl_joinProcessWithTimeout returns
136 osl_Process_E_TimedOut
137 -------------------------------------*/
139 void osl_joinProcessWithTimeout_timeout_failure()
141 oslProcess process;
142 oslProcessError osl_error = osl_executeProcess(
143 suExecutableFileURL.pData,
144 parameters_,
145 parameters_count_,
146 osl_Process_NORMAL,
147 osl_getCurrentSecurity(),
148 suCWD.pData,
149 NULL,
151 &process);
153 CPPUNIT_ASSERT_MESSAGE
155 "osl_createProcess failed",
156 osl_error == osl_Process_E_None
159 TimeValue timeout;
160 timeout.Seconds = 1;
161 timeout.Nanosec = 0;
163 osl_error = osl_joinProcessWithTimeout(process, &timeout);
165 CPPUNIT_ASSERT_MESSAGE
167 "osl_joinProcessWithTimeout returned without timeout failure",
168 osl_Process_E_TimedOut == osl_error
171 osl_error = osl_terminateProcess(process);
173 CPPUNIT_ASSERT_MESSAGE
175 "osl_terminateProcess failed",
176 osl_error == osl_Process_E_None
179 osl_freeProcessHandle(process);
182 /*-------------------------------------
183 Start a process and join with this
184 process specify a timeout so that
185 osl_joinProcessWithTimeout returns
186 osl_Process_E_None
187 -------------------------------------*/
189 void osl_joinProcessWithTimeout_without_timeout_failure()
191 oslProcess process;
192 oslProcessError osl_error = osl_executeProcess(
193 suExecutableFileURL.pData,
194 parameters_,
195 parameters_count_,
196 osl_Process_NORMAL,
197 osl_getCurrentSecurity(),
198 suCWD.pData,
199 NULL,
201 &process);
203 CPPUNIT_ASSERT_MESSAGE
205 "osl_createProcess failed",
206 osl_error == osl_Process_E_None
209 TimeValue timeout;
210 timeout.Seconds = 10;
211 timeout.Nanosec = 0;
213 osl_error = osl_joinProcessWithTimeout(process, &timeout);
215 CPPUNIT_ASSERT_MESSAGE
217 "osl_joinProcessWithTimeout returned with failure",
218 osl_Process_E_None == osl_error
221 osl_freeProcessHandle(process);
224 /*-------------------------------------
225 Start a process and join with this
226 process specify an infinite timeout
227 -------------------------------------*/
229 void osl_joinProcessWithTimeout_infinite()
231 oslProcess process;
232 oslProcessError osl_error = osl_executeProcess(
233 suExecutableFileURL.pData,
234 parameters_,
235 parameters_count_,
236 osl_Process_NORMAL,
237 osl_getCurrentSecurity(),
238 suCWD.pData,
239 NULL,
241 &process);
243 CPPUNIT_ASSERT_MESSAGE
245 "osl_createProcess failed",
246 osl_error == osl_Process_E_None
249 osl_error = osl_joinProcessWithTimeout(process, NULL);
251 CPPUNIT_ASSERT_MESSAGE
253 "osl_joinProcessWithTimeout returned with failure",
254 osl_Process_E_None == osl_error
257 osl_freeProcessHandle(process);
260 /*-------------------------------------
261 Start a process and join with this
262 process using osl_joinProcess
263 -------------------------------------*/
265 void osl_joinProcess()
267 oslProcess process;
268 oslProcessError osl_error = osl_executeProcess(
269 suExecutableFileURL.pData,
270 parameters_,
271 parameters_count_,
272 osl_Process_NORMAL,
273 osl_getCurrentSecurity(),
274 suCWD.pData,
275 NULL,
277 &process);
279 CPPUNIT_ASSERT_MESSAGE
281 "osl_createProcess failed",
282 osl_error == osl_Process_E_None
285 osl_error = ::osl_joinProcess(process);
287 CPPUNIT_ASSERT_MESSAGE
289 "osl_joinProcess returned with failure",
290 osl_Process_E_None == osl_error
293 osl_freeProcessHandle(process);
296 CPPUNIT_TEST_SUITE(Test_osl_joinProcess);
297 CPPUNIT_TEST(osl_joinProcessWithTimeout_timeout_failure);
298 CPPUNIT_TEST(osl_joinProcessWithTimeout_without_timeout_failure);
299 CPPUNIT_TEST(osl_joinProcessWithTimeout_infinite);
300 CPPUNIT_TEST(osl_joinProcess);
301 CPPUNIT_TEST_SUITE_END();
304 //#########################################################
306 typedef std::vector<std::string, rtl::Allocator<std::string> > string_container_t;
307 typedef string_container_t::const_iterator string_container_const_iter_t;
308 typedef string_container_t::iterator string_container_iter_t;
310 //#########################################################
311 class exclude : public std::unary_function<std::string, bool>
313 public:
314 //------------------------------------------------
315 exclude(const string_container_t& exclude_list)
317 string_container_const_iter_t iter = exclude_list.begin();
318 string_container_const_iter_t iter_end = exclude_list.end();
319 for (/**/; iter != iter_end; ++iter)
320 exclude_list_.push_back(env_var_name(*iter));
323 //------------------------------------------------
324 bool operator() (const std::string& env_var) const
326 return (exclude_list_.end() !=
327 std::find(
328 exclude_list_.begin(),
329 exclude_list_.end(),
330 env_var_name(env_var)));
333 private:
334 //-------------------------------------------------
335 // extract the name from an environment variable
336 // that is given in the form "NAME=VALUE"
337 std::string env_var_name(const std::string& env_var) const
339 std::string::size_type pos_equal_sign =
340 env_var.find_first_of("=");
342 if (std::string::npos != pos_equal_sign)
343 return std::string(env_var, 0, pos_equal_sign);
345 return std::string();
348 private:
349 string_container_t exclude_list_;
352 #ifdef WNT
353 void read_parent_environment(string_container_t* env_container)
355 LPTSTR env = reinterpret_cast<LPTSTR>(GetEnvironmentStrings());
356 LPTSTR p = env;
358 while (size_t l = _tcslen(p))
360 env_container->push_back(std::string(p));
361 p += l + 1;
363 FreeEnvironmentStrings(env);
365 #else
366 extern char** environ;
367 void read_parent_environment(string_container_t* env_container)
369 for (int i = 0; NULL != environ[i]; i++)
370 env_container->push_back(std::string(environ[i]));
372 #endif
374 //#########################################################
375 class Test_osl_executeProcess : public CppUnit::TestFixture
377 const OUString env_param_;
379 OUString temp_file_path_;
380 rtl_uString* parameters_[2];
381 int parameters_count_;
382 OUString suCWD;
383 OUString suExecutableFileURL;
385 public:
387 //------------------------------------------------
388 // ctor
389 Test_osl_executeProcess() :
390 env_param_(OUString::createFromAscii("-env")),
391 parameters_count_(2)
393 parameters_[0] = env_param_.pData;
394 suCWD = getExecutablePath();
395 suExecutableFileURL = suCWD;
396 suExecutableFileURL += rtl::OUString::createFromAscii("/");
397 suExecutableFileURL += EXECUTABLE_NAME;
400 //------------------------------------------------
401 virtual void setUp()
403 temp_file_path_ = create_temp_file();
404 parameters_[1] = temp_file_path_.pData;
407 //------------------------------------------------
408 OUString create_temp_file()
410 OUString temp_file_url;
411 FileBase::RC rc = FileBase::createTempFile(0, 0, &temp_file_url);
412 CPPUNIT_ASSERT_MESSAGE("createTempFile failed", FileBase::E_None == rc);
414 OUString temp_file_path;
415 rc = FileBase::getSystemPathFromFileURL(temp_file_url, temp_file_path);
416 CPPUNIT_ASSERT_MESSAGE("getSystemPathFromFileURL failed", FileBase::E_None == rc);
418 return temp_file_path;
421 //------------------------------------------------
422 void read_child_environment(string_container_t* env_container)
424 OString temp_file_name = OUStringToOString(OUString(
425 parameters_[1]), osl_getThreadTextEncoding());
426 std::ifstream file(temp_file_name.getStr());
428 CPPUNIT_ASSERT_MESSAGE
430 "I/O error, cannot open child environment file",
431 file.is_open()
434 std::string line;
435 while (std::getline(file, line))
436 env_container->push_back(line);
439 //------------------------------------------------
440 void dump_env(const string_container_t& env, OUString file_name)
442 OString fname = OUStringToOString(file_name, osl_getThreadTextEncoding());
443 std::ofstream file(fname.getStr());
444 std::ostream_iterator<std::string> oi(file, "\n");
445 std::copy(env.begin(), env.end(), oi);
448 //------------------------------------------------
449 // environment of the child process that was
450 // started. The child process writes his
451 // environment into a file
452 bool compare_environments()
454 string_container_t parent_env;
455 read_parent_environment(&parent_env);
457 string_container_t child_env;
458 read_child_environment(&child_env);
460 return ((parent_env.size() == child_env.size()) &&
461 (std::equal(child_env.begin(), child_env.end(), parent_env.begin())));
464 //------------------------------------------------
465 // compare the equal environment parts and the
466 // different part of the child environment
467 bool compare_merged_environments(const string_container_t& different_env_vars)
469 string_container_t parent_env;
470 read_parent_environment(&parent_env);
472 //remove the environment variables that we have changed
473 //in the child environment from the read parent environment
474 parent_env.erase(
475 std::remove_if(parent_env.begin(), parent_env.end(), exclude(different_env_vars)),
476 parent_env.end());
478 //read the child environment and exclude the variables that
479 //are different
480 string_container_t child_env;
481 read_child_environment(&child_env);
483 //partition the child environment into the variables that
484 //are different to the parent environment (they come first)
485 //and the variables that should be equal between parent
486 //and child environment
487 string_container_iter_t iter_logical_end =
488 std::stable_partition(child_env.begin(), child_env.end(), exclude(different_env_vars));
490 string_container_t different_child_env_vars(child_env.begin(), iter_logical_end);
491 child_env.erase(child_env.begin(), iter_logical_end);
493 bool common_env_size_equals = (parent_env.size() == child_env.size());
494 bool common_env_content_equals = std::equal(child_env.begin(), child_env.end(), parent_env.begin());
496 bool different_env_size_equals = (different_child_env_vars.size() == different_env_vars.size());
497 bool different_env_content_equals =
498 std::equal(different_env_vars.begin(), different_env_vars.end(), different_child_env_vars.begin());
500 return (common_env_size_equals && common_env_content_equals &&
501 different_env_size_equals && different_env_content_equals);
504 //------------------------------------------------
505 // test that parent and child process have the
506 // same environment when osl_executeProcess will
507 // be called with out setting new environment
508 // variables
509 void osl_execProc_parent_equals_child_environment()
511 oslProcess process;
512 oslProcessError osl_error = osl_executeProcess(
513 suExecutableFileURL.pData,
514 parameters_,
515 parameters_count_,
516 osl_Process_NORMAL,
517 NULL,
518 suCWD.pData,
519 NULL,
521 &process);
523 CPPUNIT_ASSERT_MESSAGE
525 "osl_createProcess failed",
526 osl_error == osl_Process_E_None
529 osl_error = ::osl_joinProcess(process);
531 CPPUNIT_ASSERT_MESSAGE
533 "osl_joinProcess returned with failure",
534 osl_Process_E_None == osl_error
537 osl_freeProcessHandle(process);
539 CPPUNIT_ASSERT_MESSAGE
541 "Parent an child environment not equal",
542 compare_environments()
546 //------------------------------------------------
547 #define ENV1 "PAT=a:\\"
548 #define ENV2 "PATHb=b:\\"
549 #define ENV3 "Patha=c:\\"
550 #define ENV4 "Patha=d:\\"
552 void osl_execProc_merged_child_environment()
554 rtl_uString* child_env[4];
555 OUString env1 = OUString::createFromAscii(ENV1);
556 OUString env2 = OUString::createFromAscii(ENV2);
557 OUString env3 = OUString::createFromAscii(ENV3);
558 OUString env4 = OUString::createFromAscii(ENV4);
560 child_env[0] = env1.pData;
561 child_env[1] = env2.pData;
562 child_env[2] = env3.pData;
563 child_env[3] = env4.pData;
565 oslProcess process;
566 oslProcessError osl_error = osl_executeProcess(
567 suExecutableFileURL.pData,
568 parameters_,
569 parameters_count_,
570 osl_Process_NORMAL,
571 NULL,
572 suCWD.pData,
573 child_env,
574 sizeof(child_env)/sizeof(child_env[0]),
575 &process);
577 CPPUNIT_ASSERT_MESSAGE
579 "osl_createProcess failed",
580 osl_error == osl_Process_E_None
583 osl_error = ::osl_joinProcess(process);
585 CPPUNIT_ASSERT_MESSAGE
587 "osl_joinProcess returned with failure",
588 osl_Process_E_None == osl_error
591 osl_freeProcessHandle(process);
593 string_container_t different_child_env_vars;
594 different_child_env_vars.push_back(ENV1);
595 different_child_env_vars.push_back(ENV2);
596 different_child_env_vars.push_back(ENV4);
598 CPPUNIT_ASSERT_MESSAGE
600 "osl_execProc_merged_child_environment",
601 compare_merged_environments(different_child_env_vars)
605 void osl_execProc_test_batch()
607 oslProcess process;
608 rtl::OUString suBatch = suCWD + rtl::OUString::createFromAscii("/") + rtl::OUString::createFromAscii("batch.bat");
609 oslProcessError osl_error = osl_executeProcess(
610 suBatch.pData,
611 NULL,
613 osl_Process_NORMAL,
614 NULL,
615 suCWD.pData,
616 NULL,
618 &process);
620 CPPUNIT_ASSERT_MESSAGE
622 "osl_createProcess failed",
623 osl_error == osl_Process_E_None
626 osl_error = ::osl_joinProcess(process);
628 CPPUNIT_ASSERT_MESSAGE
630 "osl_joinProcess returned with failure",
631 osl_Process_E_None == osl_error
634 osl_freeProcessHandle(process);
637 void osl_execProc_exe_name_in_argument_list()
639 rtl_uString* params[3];
641 params[0] = suExecutableFileURL.pData;
642 params[1] = env_param_.pData;
643 params[2] = temp_file_path_.pData;
644 oslProcess process;
645 oslProcessError osl_error = osl_executeProcess(
646 NULL,
647 params,
649 osl_Process_NORMAL,
650 NULL,
651 suCWD.pData,
652 NULL,
654 &process);
656 CPPUNIT_ASSERT_MESSAGE
658 "osl_createProcess failed",
659 osl_error == osl_Process_E_None
662 osl_error = ::osl_joinProcess(process);
664 CPPUNIT_ASSERT_MESSAGE
666 "osl_joinProcess returned with failure",
667 osl_Process_E_None == osl_error
670 osl_freeProcessHandle(process);
673 CPPUNIT_TEST_SUITE(Test_osl_executeProcess);
674 CPPUNIT_TEST(osl_execProc_parent_equals_child_environment);
675 CPPUNIT_TEST(osl_execProc_merged_child_environment);
676 CPPUNIT_TEST(osl_execProc_test_batch);
677 CPPUNIT_TEST(osl_execProc_exe_name_in_argument_list);
678 CPPUNIT_TEST_SUITE_END();
681 //#####################################
682 // register test suites
683 //CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(Test_osl_joinProcess, "Test_osl_joinProcess");
684 CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(Test_osl_executeProcess, "Test_osl_executeProcess");
686 NOADDITIONAL;