test_ncbi_pipe.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:15k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: test_ncbi_pipe.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 18:46:18  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.22
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: test_ncbi_pipe.cpp,v 1000.3 2004/06/01 18:46:18 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Vladimir Ivanov
  35.  *
  36.  * File Description:  Test program for the Pipe API
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <corelib/ncbiapp.hpp>
  41. #include <corelib/ncbiargs.hpp>
  42. #include <corelib/ncbienv.hpp>
  43. #include <corelib/ncbi_system.hpp>
  44. #include <connect/ncbi_conn_stream.hpp>
  45. #include <stdio.h>
  46. #include <string.h>
  47. #if defined(NCBI_OS_MSWIN)
  48. #  include <io.h>
  49. #elif defined(NCBI_OS_UNIX)
  50. #  include <unistd.h>
  51. #else
  52. #   error "Pipe tests configured for Windows and Unix only."
  53. #endif
  54. #include <test/test_assert.h>  // This header must go last
  55. USING_NCBI_SCOPE;
  56. const int    kTestResult =      99;   // Tests exit code
  57. const size_t kBufferSize = 10*1024;   // I/O buffer size
  58. ////////////////////////////////
  59. // Auxiliary functions
  60. //
  61. // Read from pipe
  62. static EIO_Status s_ReadPipe(CPipe& pipe, void* buf, size_t size,
  63.                              size_t* n_read) 
  64. {
  65.     size_t     total = 0;
  66.     size_t     cnt   = 0;
  67.     EIO_Status status;
  68.     
  69.     do {
  70.         status = pipe.Read((char*)buf + total, size - total, &cnt);
  71.         cerr << "Read from pipe: " << cnt << endl;
  72.         cerr.write((char*)buf + total, cnt);
  73.         if ( cnt ) {
  74.             cerr << endl;
  75.         }
  76.         total += cnt;
  77.     } while (status == eIO_Success  &&  total < size);    
  78.     
  79.     *n_read = total;
  80.     cerr << "Read from pipe " << total << " bytes." << endl;
  81.     return status;
  82. }
  83. // Write to pipe
  84. static EIO_Status s_WritePipe(CPipe& pipe, const void* buf, size_t size,
  85.                               size_t* n_written) 
  86. {
  87.     size_t     total = 0;
  88.     size_t     cnt   = 0;
  89.     EIO_Status status;
  90.     
  91.     do {
  92.         status = pipe.Write((char*)buf + total, size - total, &cnt);
  93.         cerr << "Written to pipe: " << cnt << endl;
  94.         cerr.write((char*)buf + total, cnt);
  95.         if ( cnt ) {
  96.             cerr << endl;
  97.         }
  98.         total += cnt;
  99.     } while (status == eIO_Success  &&  total < size);
  100.     
  101.     *n_written = total;
  102.     cerr << "Written to pipe " << total << " bytes." << endl;
  103.     return status;
  104. }
  105. // Read from file stream
  106. static string s_ReadFile(FILE* fs) 
  107. {
  108.     char   buf[kBufferSize];
  109.     size_t cnt = read(fileno(fs), buf, kBufferSize - 1);
  110.     buf[cnt] = 0;
  111.     string str = buf;
  112.     cerr << "Read from file stream " << cnt << " bytes:" << endl;
  113.     cerr.write(buf, cnt);
  114.     if ( cnt ) {
  115.         cerr << endl;
  116.     }
  117.     return str;
  118. }
  119. // Write to file stream
  120. static void s_WriteFile(FILE* fs, string message) 
  121. {
  122.     write(fileno(fs), message.c_str(), message.length());
  123.     cerr << "Written to file stream " << message.length() << " bytes:" << endl;
  124.     cerr << message << endl;
  125. }
  126. // Read from iostream
  127. static string s_ReadStream(istream& ios)
  128. {
  129.     char   buf[kBufferSize];
  130.     size_t total = 0;
  131.     size_t size  = kBufferSize - 1;
  132.     for (;;) {
  133.         ios.read(buf + total, size);
  134.         size_t cnt = ios.gcount();
  135.         cerr << "Read from iostream: " << cnt << endl;
  136.         cerr.write(buf + total, cnt);
  137.         if ( cnt ) {
  138.             cerr << endl;
  139.         }
  140.         total += cnt;
  141.         size  -= cnt;
  142.         if (size == 0  ||  (cnt == 0  &&  ios.eof())) {
  143.             break;
  144.         }
  145.         ios.clear();
  146.     }
  147.     buf[total] = 0;
  148.     string str = buf;
  149.     cerr << "Read from iostream " << total << " bytes." << endl;
  150.     return str;
  151. }
  152. ////////////////////////////////
  153. // Test application
  154. //
  155. class CTest : public CNcbiApplication
  156. {
  157. public:
  158.     void Init(void);
  159.     int Run(void);
  160. };
  161. void CTest::Init(void)
  162. {
  163.     // Set error posting and tracing on maximum
  164.     SetDiagTrace(eDT_Enable);
  165.     SetDiagPostFlag(eDPF_All);
  166.     SetDiagPostLevel(eDiag_Info);
  167. }
  168. int CTest::Run(void)
  169. {
  170.     // Initialization of variables and structures
  171.     const string app = GetArguments().GetProgramName();
  172.     string str;
  173.     vector<string> args;
  174.     char           buf[kBufferSize];
  175.     size_t         n_read    = 0;
  176.     size_t         n_written = 0;
  177.     int            exitcode  = 0;
  178.     string         message;
  179.     EIO_Status     status;
  180.     TProcessHandle handle;
  181.     // Create pipe object
  182.     CPipe pipe;
  183.     STimeout io_timeout    = {2,0};
  184.     STimeout close_timeout = {1,0};
  185.     assert(pipe.SetTimeout(eIO_Read,  &io_timeout)    == eIO_Success);
  186.     assert(pipe.SetTimeout(eIO_Write, &io_timeout)    == eIO_Success);
  187.     assert(pipe.SetTimeout(eIO_Close, &close_timeout) == eIO_Success);
  188. #if defined(NCBI_OS_UNIX)
  189.     // Pipe for reading (direct from pipe)
  190.     args.push_back("-l");
  191.     assert(pipe.Open("ls", args, CPipe::fStdIn_Close) == eIO_Success);
  192.     assert(s_WritePipe(pipe, buf, kBufferSize, &n_written) == eIO_Unknown);
  193.     assert(n_written == 0);
  194.     status = s_ReadPipe(pipe, buf, kBufferSize, &n_read);
  195.     assert(status == eIO_Success  ||  status == eIO_Closed);
  196.     assert(n_read > 0);
  197.     assert(pipe.Close(&exitcode) == eIO_Success);
  198.     assert(exitcode == 0);
  199.     // Pipe for reading (iostream)
  200.     CConn_PipeStream ios("ls", args, CPipe::fStdIn_Close);
  201.     s_ReadStream(ios);
  202.     assert(ios.GetPipe().Close(&exitcode) == eIO_Success);
  203.     assert(exitcode == 0);
  204. #elif defined (NCBI_OS_MSWIN)
  205.     string cmd = GetEnvironment().Get("COMSPEC");
  206.     // Pipe for reading (direct from pipe)
  207.     args.push_back("/c");
  208.     args.push_back("dir *.*");
  209.     assert(pipe.Open(cmd.c_str(), args, CPipe::fStdIn_Close) == eIO_Success);
  210.     assert(s_WritePipe(pipe, buf, kBufferSize, &n_written) == eIO_Unknown);
  211.     assert(n_written == 0);
  212.     status = s_ReadPipe(pipe, buf, kBufferSize, &n_read);
  213.     assert(status == eIO_Success  ||  status == eIO_Closed);
  214.     assert(n_read > 0);
  215.     assert(pipe.Close(&exitcode) == eIO_Success);
  216.     assert(exitcode == 0);
  217.     // Pipe for reading (iostream)
  218.     CConn_PipeStream ios(cmd.c_str(), args, CPipe::fStdIn_Close);
  219.     s_ReadStream(ios);
  220.     assert(ios.GetPipe().Close(&exitcode) == eIO_Success);
  221.     assert(exitcode == 0);
  222. #endif
  223.     // Pipe for writing (direct to pipe)
  224.     args.clear();
  225.     args.push_back("1");
  226.     assert(pipe.Open(app.c_str(), args, CPipe::fStdOut_Close) == eIO_Success);
  227.     assert(s_ReadPipe(pipe, buf, kBufferSize, &n_read) == eIO_Unknown);
  228.     assert(n_read == 0);
  229.     message = "Child, are you ready?";
  230.     assert(s_WritePipe(pipe, message.c_str(), message.length(),
  231.                        &n_written) == eIO_Success);
  232.     assert(n_written == message.length());
  233.     assert(pipe.Close(&exitcode) == eIO_Success);
  234.     assert(exitcode == kTestResult);
  235.     // Bidirectional pipe (direct from pipe)
  236.     args.clear();
  237.     args.push_back("2");
  238.     assert(pipe.Open(app.c_str(), args) == eIO_Success);
  239.     assert(s_ReadPipe(pipe, buf, kBufferSize, &n_read) == eIO_Timeout);
  240.     assert(n_read == 0);
  241.     message = "Child, are you ready again?";
  242.     assert(s_WritePipe(pipe, message.c_str(), message.length(),
  243.                        &n_written) == eIO_Success);
  244.     assert(n_written == message.length());
  245.     message = "Ok. Test 2 running.";
  246.     assert(s_ReadPipe(pipe, buf, kBufferSize, &n_read) == eIO_Closed);
  247.     assert(n_read == message.length());
  248.     assert(memcmp(buf, message.c_str(), n_read) == 0);
  249.     assert(s_ReadPipe(pipe, buf, kBufferSize, &n_read) == eIO_Closed);
  250.     assert(n_read == 0);
  251.     assert(pipe.Close(&exitcode) == eIO_Success);
  252.     assert(exitcode == kTestResult);
  253.     assert(s_ReadPipe(pipe, buf, kBufferSize, &n_read) == eIO_Closed);
  254.     assert(n_read == 0);
  255.     assert(s_WritePipe(pipe, buf, kBufferSize, &n_written) == eIO_Closed);
  256.     assert(n_written == 0);
  257.     // Bidirectional pipe (iostream)
  258.     args.clear();
  259.     args.push_back("3");
  260.     CConn_PipeStream ps(app.c_str(), args, CPipe::fStdErr_Open);
  261.     cout << endl;
  262.     for (int i = 5; i<=10; i++) {
  263.         int value; 
  264.         cout << "How much is " << i << "*" << i << "?t";
  265.         ps << i << endl;
  266.         ps.flush();
  267.         ps >> value;
  268.         cout << value << endl;
  269.         assert(ps.good());
  270.         assert(value == i*i);
  271.     }
  272.     ps.GetPipe().SetReadHandle(CPipe::eStdErr);
  273.     ps >> str;
  274.     cout << str << endl;
  275.     assert(str == "Done");
  276.     assert(ps.GetPipe().Close(&exitcode) == eIO_Success);
  277.     assert(exitcode == kTestResult);
  278.     // f*OnClose flags test
  279.     args.clear();
  280.     args.push_back("4");
  281.     
  282.     assert(pipe.Open(app.c_str(), args, CPipe::fKeepOnClose) == eIO_Success);
  283.     handle = pipe.GetProcessHandle();
  284.     assert(handle > 0);
  285.     assert(pipe.Close(&exitcode) == eIO_Timeout);
  286.     assert(exitcode == -1 );
  287.     {{
  288.         CProcess process(handle, CProcess::eHandle);
  289.         assert(process.IsAlive());
  290.         assert(process.Kill());
  291.         assert(!process.IsAlive());
  292.     }}
  293.     args.clear();
  294.     args.push_back("4");
  295.     assert(pipe.Open(app.c_str(), args, CPipe::fKillOnClose) == eIO_Success);
  296.     handle = pipe.GetProcessHandle();
  297.     assert(handle > 0);
  298.     assert(pipe.Close(&exitcode) == eIO_Success);
  299.     assert(exitcode == -1 );
  300.     {{
  301.         CProcess process(handle, CProcess::eHandle);
  302.         assert(!process.IsAlive());
  303.     }}
  304.     assert(pipe.Open(app.c_str(), args, CPipe::fKeepOnClose) == eIO_Success);
  305.     handle = pipe.GetProcessHandle();
  306.     assert(handle > 0);
  307.     assert(pipe.Close(&exitcode) == eIO_Timeout);
  308.     assert(exitcode == -1);
  309.     {{
  310.         CProcess process(handle, CProcess::eHandle);
  311.         assert(process.IsAlive());
  312.         assert(process.Wait(4000) == kTestResult);
  313.         assert(!process.IsAlive());
  314.     }}
  315.     // Done
  316.     cout << "nTEST execution completed successfully!n";
  317.     return 0;
  318. }
  319. ///////////////////////////////////
  320. // APPLICATION OBJECT  and  MAIN
  321. //
  322. int main(int argc, const char* argv[])
  323. {
  324.     string command;
  325.     // Check arguments
  326.     if (argc > 2) {
  327.         // Invalid arguments
  328.         exit(1);
  329.     }
  330.     if (argc == 1) {
  331.         // Execute main application function
  332.         return CTest().AppMain(argc, argv, 0, eDS_Default, 0);
  333.     }
  334.     // Internal tests
  335.     int test_num = NStr::StringToInt(argv[1]);
  336.     switch ( test_num ) {
  337.     // Spawned process for unidirectional test
  338.     case 1:
  339.     {
  340.         cerr << endl << "--- CPipe unidirectional test ---" << endl;
  341.         command = s_ReadFile(stdin);
  342.         _TRACE("read back >>" << command << "<<");
  343.         assert(command == "Child, are you ready?");
  344.         cerr << "Ok. Test 1 running." << endl;
  345.         exit(kTestResult);
  346.     }
  347.     // Spawned process for bidirectional test (direct from pipe)
  348.     case 2:
  349.     {
  350.         cerr << endl << "--- CPipe bidirectional test (pipe) ---" << endl;
  351.         command = s_ReadFile(stdin);
  352.         assert(command == "Child, are you ready again?");
  353.         s_WriteFile(stdout, "Ok. Test 2 running.");
  354.         exit(kTestResult);
  355.     }
  356.     // Spawned process for bidirectional test (iostream)
  357.     case 3:
  358.     {
  359.         //cerr << endl << "--- CPipe bidirectional test (iostream) ---"<<endl;
  360.         for (int i = 5; i<=10; i++) {
  361.             int value;
  362.             cin >> value;
  363.             assert(value == i);
  364.             cout << value*value << endl;
  365.             cout.flush();
  366.         }
  367.         cerr << "Done" << endl;
  368.         exit(kTestResult);
  369.     }
  370.     // Test for fKeepOnClose && fKillOnClose flags
  371.     case 4:
  372.     {
  373.         SleepSec(3);
  374.         exit(kTestResult);
  375.     }}
  376.     return -1;
  377. }
  378. /*
  379.  * ===========================================================================
  380.  * $Log: test_ncbi_pipe.cpp,v $
  381.  * Revision 1000.3  2004/06/01 18:46:18  gouriano
  382.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.22
  383.  *
  384.  * Revision 6.22  2004/05/17 20:58:22  gorelenk
  385.  * Added include of PCH ncbi_pch.hpp
  386.  *
  387.  * Revision 6.21  2003/12/04 16:29:22  ivanov
  388.  * Added f*OnClose flags test
  389.  *
  390.  * Revision 6.20  2003/11/15 15:35:36  ucko
  391.  * +<stdio.h> (no longer included by ncbi_pipe.hpp)
  392.  *
  393.  * Revision 6.19  2003/11/12 16:43:36  ivanov
  394.  * Using SetReadHandle() through GetPipe()
  395.  *
  396.  * Revision 6.18  2003/09/30 21:00:34  lavr
  397.  * Formatting
  398.  *
  399.  * Revision 6.17  2003/09/23 21:13:32  lavr
  400.  * Adapt test for new stream and pipe API
  401.  *
  402.  * Revision 6.16  2003/09/10 15:54:47  ivanov
  403.  * Rewritten s_ReadPipe/s_WritePipe with using I/O loops.
  404.  * Removed unused Delay().
  405.  *
  406.  * Revision 6.15  2003/09/09 19:42:19  ivanov
  407.  * Added more checks
  408.  *
  409.  * Revision 6.14  2003/09/02 20:38:10  ivanov
  410.  * Changes concerned moving ncbipipe to CONNECT library from CORELIB and
  411.  * rewritting CPipe class using I/O timeouts.
  412.  *
  413.  * Revision 6.13  2003/04/23 20:57:45  ivanov
  414.  * Slightly changed static read/write functions. Minor cosmetics.
  415.  *
  416.  * Revision 6.12  2003/03/07 16:24:44  ivanov
  417.  * Simplify Delay(). Added a delays before checking exit code of a
  418.  * pipe'd application.
  419.  *
  420.  * Revision 6.11  2003/03/06 21:19:16  ivanov
  421.  * Added comment for R6.10:
  422.  * Run the "dir" command for MS Windows via default command interpreter.
  423.  *
  424.  * Revision 6.10  2003/03/06 21:12:35  ivanov
  425.  * *** empty log message ***
  426.  *
  427.  * Revision 6.9  2003/03/03 14:47:21  dicuccio
  428.  * Remplemented CPipe using private platform specific classes.  Remplemented
  429.  * Win32 pipes using CreatePipe() / CreateProcess() - enabled CPipe in windows
  430.  * subsystem
  431.  *
  432.  * Revision 6.8  2002/08/14 14:33:29  ivanov
  433.  * Changed allcalls _exit() to exit() back -- non crossplatform function
  434.  *
  435.  * Revision 6.7  2002/08/13 14:09:48  ivanov
  436.  * Changed exit() to _exit() in the child's branch of the test
  437.  *
  438.  * Revision 6.6  2002/06/24 21:44:36  ivanov
  439.  * Fixed s_ReadFile(), c_ReadStream()
  440.  *
  441.  * Revision 6.5  2002/06/12 14:01:38  ivanov
  442.  * Increased size of read buffer. Fixed s_ReadStream().
  443.  *
  444.  * Revision 6.4  2002/06/11 19:25:56  ivanov
  445.  * Added tests for CPipeIOStream
  446.  *
  447.  * Revision 6.3  2002/06/10 18:49:08  ivanov
  448.  * Fixed argument passed to child process
  449.  *
  450.  * Revision 6.2  2002/06/10 18:35:29  ivanov
  451.  * Changed argument's type of a running child program from char*[]
  452.  * to vector<string>
  453.  *
  454.  * Revision 6.1  2002/06/10 17:00:30  ivanov
  455.  * Initial revision
  456.  *
  457.  * ===========================================================================
  458.  */