// ChildWatcher_t.cxx #include "dial_job/ChildWatcher.h" #include #include #include #include #include "dataset_util/Environment.h" using std::string; using std::ostream; using std::cout; using std::endl; using std::vector; using dial::ChildWatcher; void msg(string msg) { cout << "----- "; cout << msg; cout << " -----" << endl; } pid_t PID = 0; int COUNT = 0; int RETURN = -1; int COUNTER = 0; void count1(pid_t pid, int rstat) { PID = pid; ++COUNT; RETURN = rstat; COUNTER = 1; } void count2(pid_t pid, int rstat) { PID = pid; ++COUNT; RETURN = rstat; COUNTER = 1; } int ChildWatcher_t() { string plat = Environment::initial().value("CTG_PLATFORM"); if ( plat == "rh73_gcc323" ) { msg("Skipping test of ChildWatcher on " + plat); return 0; } msg("Check initial status"); ChildWatcher::print(cout) << endl; msg("Initialize"); assert( ChildWatcher::initialize() == 0 ); ChildWatcher::print(cout) << endl; assert( ChildWatcher::live_count() == 0 ); assert( ChildWatcher::dead_count() == 0 ); assert( ChildWatcher::unborn_count() == 0 ); assert( ! ChildWatcher::pending() ); assert( ChildWatcher::is_blocked() ); msg("Renitialize"); assert( ChildWatcher::initialize() == 0 ); ChildWatcher::print(cout) << endl; assert( ChildWatcher::live_count() == 0 ); assert( ChildWatcher::dead_count() == 0 ); assert( ChildWatcher::unborn_count() == 0 ); assert( ! ChildWatcher::pending() ); assert( ChildWatcher::is_blocked() ); msg("Unblock end-of-child signal"); assert( ChildWatcher::unblock() ); ChildWatcher::print(cout) << endl; assert( ! ChildWatcher::is_blocked() ); msg("Block end-of-child signal"); assert( ! ChildWatcher::block() ); ChildWatcher::print(cout) << endl; assert( ChildWatcher::is_blocked() ); msg("Register a process"); pid_t pid1; { int fstat = fork(); if ( fstat == 0 ) { const char* com = "/bin/sleep"; const char* argv[] = { "sleep", "3", 0 }; char* const* args = const_cast(argv); execvp(com, args); assert(false); } pid1 = fstat; assert( ChildWatcher::watch(pid1,count1) == 0 ); assert( ChildWatcher::is_registered(pid1) ); assert( ChildWatcher::is_live(pid1) ); } ChildWatcher::print(cout) << endl; msg("Register another process"); pid_t pid2; { int fstat = fork(); if ( fstat == 0 ) { const char* com = "/bin/ls"; const char* argv[] = { "ls", "NoSuchFile", 0 }; char* const* args = const_cast(argv); execvp(com, args); assert(false); } pid2 = fstat; assert( ChildWatcher::watch(pid2,count2) == 0 ); assert( ChildWatcher::is_registered(pid2) ); assert( ChildWatcher::is_live(pid2) ); } ChildWatcher::print(cout) << endl; msg("Wait for second child process"); sleep(2); ChildWatcher::print(cout) << endl; assert( ChildWatcher::live_count() == 2 ); assert( ChildWatcher::dead_count() == 0 ); assert( ChildWatcher::unborn_count() == 0 ); assert( ChildWatcher::pending() ); msg("Update"); ChildWatcher::update(); assert( ChildWatcher::is_blocked() ); ChildWatcher::print(cout) << endl; assert( ChildWatcher::live_count() == 1 ); assert( ChildWatcher::dead_count() == 1 ); assert( ChildWatcher::unborn_count() == 0 ); assert( ! ChildWatcher::pending() ); assert( COUNT == 1 ); assert( PID == pid2 ); assert( RETURN != 0 ); msg("Wait for first child process"); for ( int i=0; i<10; ++i ) { cout << "... " << i << endl; sleep(1); if ( ChildWatcher::update() == 0 ) break; } ChildWatcher::print(cout) << endl; assert( ChildWatcher::live_count() == 0 ); assert( ChildWatcher::dead_count() == 2 ); assert( ChildWatcher::unborn_count() == 0 ); assert( COUNT == 2 ); assert( PID == pid1 ); assert( RETURN == 0 ); return 0; } #ifdef CTEST_MAIN int main() { return ChildWatcher_t(); } #endif