test_ncbi_process.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:8k
- /*
- * ===========================================================================
- * PRODUCTION $Log: test_ncbi_process.cpp,v $
- * PRODUCTION Revision 1000.1 2004/06/01 19:09:49 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.3
- * PRODUCTION
- * ===========================================================================
- */
- /* $Id: test_ncbi_process.cpp,v 1000.1 2004/06/01 19:09:49 gouriano Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Authors: Aaron Ucko, Vladimir Ivanov
- *
- *
- */
- #include <ncbi_pch.hpp>
- #include <corelib/ncbiapp.hpp>
- #include <corelib/ncbienv.hpp>
- #include <corelib/ncbiargs.hpp>
- #include <corelib/ncbiexec.hpp>
- #include <corelib/ncbifile.hpp>
- #include <corelib/ncbi_system.hpp>
- #include <corelib/ncbi_process.hpp>
- #include <test/test_assert.h> /* This header must go last */
- USING_NCBI_SCOPE;
- /////////////////////////////////
- // General tests
- //
- static void Test_Process(void)
- {
- LOG_POST("nProcess tests:n");
- string app = CNcbiApplication::Instance()->GetArguments().GetProgramName();
- TPid pid;
- {{
- LOG_POST("CMD = " << app << " -sleep 3");
- pid = CExec::SpawnL(CExec::eNoWait, app.c_str(), "-sleep", "3", 0);
- LOG_POST("PID = " << pid);
- CProcess process(pid, CProcess::eHandle);
- assert(process.IsAlive());
- assert(process.Wait() == 88);
- assert(!process.IsAlive());
- }}
- {{
- LOG_POST("CMD = " << app << " -sleep 10");
- pid = CExec::SpawnL(CExec::eNoWait, app.c_str(), "-sleep", "10", 0);
- LOG_POST("PID = " << pid);
- CProcess process(pid, CProcess::eHandle);
- assert(process.IsAlive());
- assert( process.Wait(2000) == -1);
- assert(process.Kill());
- assert(!process.IsAlive());
- int exitcode = process.Wait();
- LOG_POST("Wait(pid) = " << exitcode);
- assert(exitcode != 88);
- }}
- }
- /////////////////////////////////
- // PIDGuard test
- //
- // NOTE: ppid is int rather than TPid in these two functions because we need
- // it to be signed.
- static void Test_PIDGuardChild(int ppid, string lockfile)
- {
- string s_app =
- CNcbiApplication::Instance()->GetArguments().GetProgramName();
- string s_pid = NStr::IntToString(ppid);
- int ret_code = CExec::SpawnL(CExec::eWait, s_app.c_str(),
- "-parent", s_pid.c_str() ,
- "-lockfile", lockfile.c_str(), 0);
- assert( !ret_code );
- }
- static void Test_PIDGuard(int ppid, string lockfile)
- {
- if (lockfile.empty()) {
- // Fixed names are usually more appropriate, but here we don't
- // want independent tests to step on each other....
- lockfile = CFile::GetTmpName();
- }
- CFile lf(lockfile);
- TPid my_pid = CProcess::GetCurrentPid();
- assert(my_pid > 0);
- LOG_POST("nTest_PIDGuard starting:nmy_pid = " << my_pid
- << ", ppid = " << ppid << ", lockfile = " << lockfile << 'n');
- // Parent
- if (ppid == 0) {
- CPIDGuard guard(lockfile);
- {
- CPIDGuard guard2(lockfile);
- }
- assert(lf.Exists());
- Test_PIDGuardChild(my_pid, lockfile);
- assert(lf.Exists());
- guard.Release();
- assert(!lf.Exists());
- Test_PIDGuardChild(-1, lockfile);
- assert(lf.Exists());
- #if defined(NCBI_OS_MSWIN)
- // Additional check on stuck child process.
- //
- // On some Windows machines OS report that child process is still
- // running even if we already have its exit code.
- CNcbiIfstream in(lockfile.c_str());
- if (in.good()) {
- int child_pid = 0;
- in >> child_pid;
- if ( child_pid > 0 ) {
- CProcess child(child_pid, CProcess::ePid);
- child.Wait();
- }
- }
- in.close();
- #endif
- Test_PIDGuardChild(-2, lockfile);
- assert(!lf.Exists());
- }
- // Child run with parent lock open
- else if (ppid > 0) {
- try {
- LOG_POST("Expect an exception now.");
- CPIDGuard guard(lockfile);
- ERR_POST("Should have been locked (by parent)");
- _TROUBLE;
- } catch (CPIDGuardException& e) {
- LOG_POST(e.what());
- assert(e.GetErrCode() == CPIDGuardException::eStillRunning);
- assert(e.GetPID() == ppid);
- }
- } else if (ppid == -1) {
- new CPIDGuard(lockfile); // deliberate leak
- LOG_POST("Left stale lock.");
- } else if (ppid == -2) {
- CPIDGuard guard(lockfile);
- TPid old_pid = guard.GetOldPID();
- assert(old_pid > 0);
- LOG_POST("Old PID was " << old_pid);
- } else {
- _TROUBLE;
- }
- CPIDGuard unique_guard(CFile::GetTmpName());
- }
- /////////////////////////////////
- // Test application
- //
- class CTestApplication : public CNcbiApplication
- {
- public:
- virtual void Init(void);
- virtual int Run (void);
- };
- void CTestApplication::Init(void)
- {
- // Set error posting and tracing on maximum
- SetDiagTrace(eDT_Enable);
- SetDiagPostFlag(eDPF_All);
- SetDiagPostLevel(eDiag_Info);
- // Create command-line argument descriptions class
- auto_ptr<CArgDescriptions> arg_desc(new CArgDescriptions);
- // Specify USAGE context
- arg_desc->SetUsageContext(GetArguments().GetProgramBasename(),
- "Test process management functions");
- // Specific to Process test
- arg_desc->AddDefaultKey("sleep", "sec", "for internal use only",
- CArgDescriptions::eInteger, "0");
- // Specific to PID guard test
- arg_desc->AddDefaultKey("parent", "PID", "for internal use only",
- CArgDescriptions::eInteger, "0");
- arg_desc->AddDefaultKey("lockfile", "filename", "parent's lock file",
- CArgDescriptions::eString, kEmptyStr);
- // Setup arg.descriptions for this application
- SetupArgDescriptions(arg_desc.release());
- }
- int CTestApplication::Run(void)
- {
- CArgs args = GetArgs();
- // Is this an instance executed from process test?
- int sec = args["sleep"].AsInteger();
- if ( sec ) {
- LOG_POST("Client is sleeping " << sec << " sec.");
- SleepSec(sec);
- return 88;
- }
- // Main tests
- // General tests
- if ( !args["parent"].AsInteger() ) {
- Test_Process();
- }
- // PIDGuard tests
- Test_PIDGuard(args["parent"].AsInteger(), args["lockfile"].AsString());
- return 0;
- }
-
- ///////////////////////////////////
- // APPLICATION OBJECT and MAIN
- //
- static CTestApplication theTestApplication;
- int main(int argc, const char* argv[])
- {
- // Execute main application function
- return theTestApplication.AppMain(argc, argv, 0, eDS_Default, 0);
- }
- /*
- * ===========================================================================
- * $Log: test_ncbi_process.cpp,v $
- * Revision 1000.1 2004/06/01 19:09:49 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.3
- *
- * Revision 1.3 2004/05/18 17:05:31 ivanov
- * CPIDGuard tests:
- * Use CExec::SpawnL() instead System() to run child process.
- * Added some new asserts.
- *
- * Revision 1.2 2004/05/14 13:59:51 gorelenk
- * Added include of ncbi_pch.hpp
- *
- * Revision 1.1 2003/09/25 16:59:11 ivanov
- * Initial revision
- *
- * ===========================================================================
- */