diff options
Diffstat (limited to 'ACE/tests/Process_Manager_Test.cpp')
-rw-r--r-- | ACE/tests/Process_Manager_Test.cpp | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/ACE/tests/Process_Manager_Test.cpp b/ACE/tests/Process_Manager_Test.cpp new file mode 100644 index 00000000000..3ceb16c51cb --- /dev/null +++ b/ACE/tests/Process_Manager_Test.cpp @@ -0,0 +1,320 @@ +// $Id$ + +// ============================================================================ +// +// = LIBRARY +// tests +// +// = FILENAME +// Process_Manager_Test.cpp +// +// = DESCRIPTION +// This program tests the various methods provided by +// <ACE_Process_Manager>. It illustrates both the explicit <wait> +// functions and the Reactor-style auto-reaping. There's an +// Exit_Handler class that can print out (in Debug mode) when a +// child has been reaped. +// +// The child processes spawned are simply this program itself, with +// an integer argument specifying how long to "process" (actually, +// the child just sleeps for the specified length of time). +// +// = AUTHOR +// Douglas C. Schmidt <schmidt@cs.wustl.edu> and +// Dave Madden <dhm@mersenne.com> +// +// ============================================================================ + +#include "test_config.h" +#include "ace/OS_NS_unistd.h" +#include "ace/Process_Manager.h" +#include "ace/Get_Opt.h" +#include "ace/Thread.h" +#include "ace/Reactor.h" + +ACE_RCSID(tests, Process_Manager_Test, "Process_Manager_Test.cpp,v 4.11 1999/09/02 04:36:30 schmidt Exp") + +static u_int debug_test = 0; + +class Exit_Handler : public ACE_Event_Handler +{ +public: + Exit_Handler (const char *msg): msg_ (msg) { } + + virtual ~Exit_Handler (void) { } + + virtual int handle_close (ACE_HANDLE, ACE_Reactor_Mask) + { + delete this; + return 0; + } + + virtual int handle_exit (ACE_Process *proc) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) Exit_Handler(%s) got %d: %d\n"), + msg_, + int (proc->getpid ()), + int (proc->exit_code ()) )); + return 0; + } +private: + const char *msg_; +}; + +static void +usage (const ACE_TCHAR *argv0) +{ + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("usage: %s [-d] [sleep-seconds]\n"), + argv0)); + ACE_OS::exit (0); +} + +static pid_t +spawn_child (const ACE_TCHAR *argv0, + ACE_Process_Manager &mgr, + int sleep_time = 0) +{ +#if defined (ACE_WIN32) +const ACE_TCHAR *cmdline_format = ACE_TEXT("\"%s\" %s %d"); +#elif !defined (ACE_USES_WCHAR) +const ACE_TCHAR *cmdline_format = ACE_TEXT (".") ACE_DIRECTORY_SEPARATOR_STR ACE_TEXT("%s %s %d"); +#else +const ACE_TCHAR *cmdline_format = ACE_TEXT (".") ACE_DIRECTORY_SEPARATOR_STR ACE_TEXT("%ls %ls %d"); +#endif + ACE_Process_Options opts; + + opts.command_line (cmdline_format, + argv0, + debug_test ? ACE_TEXT ("-d") : ACE_TEXT (""), + sleep_time); + + pid_t result = mgr.spawn (opts); + + if (result != ACE_INVALID_PID) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) spawned child: pid %d time %d\n"), + int (result), sleep_time)); + else + ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("spawn failed"))); + + return result; +} + +int +run_main (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt args (argc, argv, ACE_TEXT ("d")); + + for (int arg = args (); arg != EOF; arg = args ()) + switch (arg) + { + case 'd': + debug_test = 1u; + break; + default: + usage (argv[0]); + break; + } + + if (args.opt_ind () == argc - 1) + { + // child process: sleep & exit + ACE_TCHAR lognm[MAXPATHLEN]; + int mypid (ACE_OS::getpid ()); + ACE_OS::sprintf(lognm, ACE_TEXT ("Process_Manager_Test-child-%d"), mypid); + + ACE_START_TEST (lognm); + int secs = ACE_OS::atoi (argv[args.opt_ind ()]); + ACE_OS::sleep (secs ? secs : 1); + if (debug_test) + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("%T: pid %P about to exit with code %d\n"), + secs)); + ACE_END_LOG; + + return secs; + } + + if (args.opt_ind () != argc) // incorrect usage + usage (argv[0]); + + ACE_START_TEST (ACE_TEXT ("Process_Manager_Test")); + + // Try the explicit <ACE_Process_Manager::wait> functions + + int result = 0, test_status = 0; + ACE_Process_Manager mgr; + + mgr.register_handler (new Exit_Handler ("default")); + + ACE_exitcode exitcode; + + // -------------------------------------------------- + // wait for a specific PID + pid_t child1 = spawn_child (argv[0], + mgr, + 1); + result = mgr.wait (child1, + &exitcode); + + if (result != child1) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("Error: expected to reap child1 (%d); got %d\n"), + child1, + result)); + if (result == ACE_INVALID_PID) + ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("error"))); + test_status = 1; + } + else + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) reaped child1, pid %d: %d\n"), + child1, + exitcode)); + + // -------------------------------------------------- + // wait for a specific PID; another should finish first + pid_t child2 = spawn_child (argv[0], + mgr, + 1); + pid_t child3 = spawn_child (argv[0], + mgr, + 4); + result = mgr.wait (child3, + &exitcode); + + if (result != child3) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("Error: expected to reap child3 (%d); got %d\n"), + child3, + result)); + if (result == ACE_INVALID_PID) + ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("error"))); + test_status = 1; + } + else + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) reaped child 3, pid %d: %d\n"), + child3, + exitcode)); + + // Now wait for any...should get the one that finished earlier. + + result = mgr.wait (0, &exitcode); + + if (result != child2) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("Error: expected to reap child2 (%d); got %d\n"), + child2, + result)); + if (result == ACE_INVALID_PID) + ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("error"))); + test_status = 1; + } + else + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) reaped child 2, pid %d: %d\n"), + result, + exitcode)); + + // -------------------------------------------------- + // Try the timed wait functions + + // This one shouldn't timeout: + pid_t child4 = spawn_child (argv[0], + mgr, + 1); + result = mgr.wait (0, ACE_Time_Value (4), &exitcode); + + if (result != child4) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("Error: expected to reap child4 (%d); got %d\n"), + child4, + result)); + if (result == ACE_INVALID_PID) + ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("error"))); + test_status = 1; + } + else + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) reaped child 4 pid %d: %d\n"), + result, + exitcode)); + + // This one should timeout: + pid_t child5 = spawn_child (argv[0], + mgr, + 4); + result = mgr.wait (0, ACE_Time_Value (1), &exitcode); + if (result != 0) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("Error: expected wait to time out; got %d\n"), + result)); + if (result == ACE_INVALID_PID) + ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("error"))); + test_status = 1; + } + else + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) Correctly timed out wait at child 5\n"))); + + // Now wait indefinitely to clean up... + result = mgr.wait (0, &exitcode); + + if (result != child5) + { + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("Error: expected to reap child5 pid %d; got %d\n"), + child5, + result)); + if (result == ACE_INVALID_PID) + ACE_ERROR ((LM_ERROR, ACE_TEXT ("%p\n"), ACE_TEXT ("error"))); + test_status = 1; + } + else + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) reaped child 5, pid %d: %d\n"), + result, + exitcode)); + +#if !defined (ACE_OPENVMS) + // -------------------------------------------------- + // Finally, try the reactor stuff... + mgr.open (ACE_Process_Manager::DEFAULT_SIZE, + ACE_Reactor::instance ()); + + pid_t child6 = spawn_child (argv[0], + mgr, + 5); + /* pid_t child7 = */ spawn_child (argv[0], + mgr, + 6); + + mgr.register_handler (new Exit_Handler ("specific"), + child6); + + ACE_Time_Value how_long (10); + + ACE_Reactor::instance ()->run_reactor_event_loop (how_long); + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("(%P) Reactor loop done!\n") )); + + size_t nr_procs = mgr.managed (); + if (nr_procs != 0) + ACE_ERROR ((LM_ERROR, + ACE_TEXT ("(%P) %d processes left in manager\n"), + nr_procs)); + +#endif + ACE_END_TEST; + return test_status; +} + |