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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: pbacktest.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:42:34  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: pbacktest.cpp,v 1000.3 2004/06/01 19:42:34 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:  Anton Lavrentiev
  35.  *
  36.  * File Description:
  37.  *   Test CStreamUtils::Pushback() interface.
  38.  *
  39.  */
  40. #include <ncbi_pch.hpp>
  41. #include "pbacktest.hpp"
  42. #include <corelib/ncbidbg.hpp>
  43. #include <util/stream_utils.hpp>
  44. #include <stdlib.h>
  45. #include <time.h>
  46. #include <test/test_assert.h>  /* This header must go last */
  47. #define _STR(a) #a
  48. #define  STR(a) _STR(a)
  49. BEGIN_NCBI_SCOPE
  50. static const size_t kBufferSize = 512*1024;
  51. /* NOTE about MSVC compiler and its C++ std. library:
  52.  *
  53.  * The C++ standard is very confusing on the stream's ability to do
  54.  * pushback() and unget(); it says nothing about the case whether
  55.  * they are guaranteed, and if so, under what circumstances.
  56.  * The only clear message is seen in "The C++ Programming Language",
  57.  * 3rd ed. by B.Stroustrup, p.644, which reads "what is guaranteed
  58.  * is that you can back up one character after a successful read."
  59.  *
  60.  * Most implementation obey this; but there are some that do not.
  61.  *
  62.  * A bug or not a bug, we had to put putback and unget tests to only
  63.  * follow a first pushback operation, which (internally) changes the
  64.  * stream buffer and always keeps "usual backup condition", described in
  65.  * the standard, thus allowing at least one-char backup after a read.
  66.  *
  67.  * So, if you plan to do a portable backup, which can possibly follow
  68.  * an unformatted read, do so by using CStreamUtils::Pushback() instead of
  69.  * standard means, as the latter may be broken.
  70.  */
  71. extern int TEST_StreamPushback(iostream&    ios,
  72.                                unsigned int seed_in,
  73.                                bool         rewind)
  74. {
  75.     size_t i, j, k;
  76.     LOG_POST("Generating array of random data");
  77.     unsigned int seed = seed_in ? seed_in : (unsigned int) time(0);
  78.     LOG_POST("Seed = " << seed);
  79.     srand(seed);
  80.     char *buf1 = new char[kBufferSize + 1];
  81.     char *buf2 = new char[kBufferSize + 2];
  82.     for (j = 0; j < kBufferSize/1024; j++) {
  83.         for (i = 0; i < 1024 - 1; i++)
  84.             buf1[j*1024 + i] = "0123456789"[rand() % 10];
  85.         buf1[j*1024 + 1024 - 1] = 'n';
  86.     }
  87.     buf1[kBufferSize] = '';
  88.     LOG_POST("Sending data down the stream");
  89.     if (!(ios << buf1)) {
  90.         ERR_POST("Could not send data");
  91.         return 1;
  92.     }
  93.     if (rewind)
  94.         ios.seekg(0);
  95.     LOG_POST("Doing random reads and pushbacks of the reply");
  96.     char c = 0;
  97.     size_t buflen = 0;
  98. #ifdef NCBI_COMPILER_MSVC
  99.     bool first_pushback_done = false;
  100. #endif
  101.     for (k = 0; buflen < kBufferSize; k++) {
  102.         size_t m = kBufferSize + 1 - buflen;
  103.         if (m > 10)
  104.             m /= 10;
  105.         i = rand() % m + 1;
  106.         if (buflen + i > kBufferSize + 1)
  107.             i = kBufferSize + 1 - buflen;
  108.         LOG_POST(Info << "Reading " << i << " byte" << (i == 1 ? "" : "s"));
  109.         // Force at least minimal blocking, since Readsome might not
  110.         // block at all and accepting 0-byte reads could lead to spinning.
  111.         ios.peek();
  112.         j = CStreamUtils::Readsome(ios, &buf2[buflen], i);
  113.         if (!ios.good()) {
  114.             ERR_POST("Error receiving data");
  115.             return 2;
  116.         }
  117.         if (j != i)
  118.             LOG_POST("Bytes requested: " << i << ", received: " << j);
  119.         assert(j > 0);
  120.         if (c && buf2[buflen] != c) {
  121.             LOG_POST(Error <<
  122.                      "Mismatch, putback: " << c << ", read: " << buf2[buflen]);
  123.             return 2;
  124.         } else
  125.             c = 0;
  126.         buflen += j;
  127.         bool pback = false;
  128.         if (rewind  &&  rand() % 7 == 0  &&  buflen < kBufferSize) {
  129.             if (rand() & 1) {
  130.                 LOG_POST(Info << "Testing pre-seekg(" << buflen << ", "
  131.                          << STR(IOS_BASE) "::beg)");
  132.                 ios.seekg(buflen, IOS_BASE::beg);
  133.             } else {
  134.                 LOG_POST(Info << "Testing pre-seekg(" << buflen << ')');
  135.                 ios.seekg(buflen);
  136.             }
  137.             if (!ios.good()) {
  138.                 ERR_POST("Error in stream re-positioning");
  139.                 return 2;
  140.             }
  141.         } else if (ios.good()  &&  rand() % 5 == 0  &&  j > 1) {
  142. #ifdef NCBI_COMPILER_MSVC
  143.             if (!rewind || first_pushback_done) {
  144. #endif
  145.                 c = buf2[--buflen];
  146.                 if (rand() & 1) {
  147.                     LOG_POST(Info << "Putback ('" << c << "')");
  148.                     ios.putback(c);
  149.                 } else {
  150.                     LOG_POST(Info << "Unget ('" << c << "')");
  151.                     ios.unget();
  152.                 }
  153.                 if (!ios.good()) {
  154.                     ERR_POST("Error putting a byte back");
  155.                     return 2;
  156.                 }
  157.                 j--;
  158.                 pback = true;
  159. #ifdef NCBI_COMPILER_MSVC
  160.             }
  161. #endif
  162.         }
  163.         i = rand() % j + 1;
  164.         if (i != j || --i) {
  165.             buflen -= i;
  166.             LOG_POST(Info << "Pushing back " << i <<
  167.                      " byte" << (i == 1 ? "" : "s"));
  168.             CStreamUtils::Pushback(ios, &buf2[buflen], i);
  169.             c = buf2[buflen];
  170. #ifdef NCBI_COMPILER_MSVC
  171.             first_pushback_done = true;
  172. #endif
  173.             pback = true;
  174.         }
  175.         if (rewind  &&  rand() % 9 == 0  &&  buflen < kBufferSize) {
  176.             if (pback) {
  177.                 buflen++;
  178.                 c = 0;
  179.             }
  180.             if (rand() & 1) {
  181.                 LOG_POST(Info << "Tesing post-seekg(" << buflen << ')');
  182.                 ios.seekg(buflen);
  183.             } else {
  184.                 LOG_POST(Info << "Tesing post-seekg(" << buflen << ", "
  185.                          << STR(IOS_BASE) << "::beg)");
  186.                 ios.seekg(buflen, IOS_BASE::beg);
  187.             }
  188.             if (!ios.good()) {
  189.                 ERR_POST("Error in stream re-positioning");
  190.                 return 2;
  191.             }
  192.         }
  193.         //LOG_POST(Info << "Obtained " << buflen << " of " << kBufferSize);
  194.     }
  195.     LOG_POST(Info << buflen << " bytes obtained in " << k << " iteration(s)" <<
  196.              (ios.eof() ? " (EOF)" : ""));
  197.     buf2[buflen] = '';
  198.     for (i = 0; i < kBufferSize; i++) {
  199.         if (!buf2[i]) {
  200.             ERR_POST("Zero byte within encountered at position " << i + 1);
  201.             return 1;
  202.         }
  203.         if (buf2[i] != buf1[i]) {
  204.             ERR_POST("In: '" << buf1[i] << "', Out: '" << buf2[i] << '''
  205.                      << " at position " << i + 1);
  206.             return 1;
  207.         }
  208.     }
  209.     if (buflen > kBufferSize) {
  210.         ERR_POST("Sent: " << kBufferSize << ", bounced: " << buflen);
  211.         return 1;
  212.     } else
  213.         LOG_POST(Info << "Test passed");
  214.     delete[] buf1;
  215.     delete[] buf2;
  216.     return 0/*okay*/;
  217. }
  218. END_NCBI_SCOPE
  219. /*
  220.  * ===========================================================================
  221.  * $Log: pbacktest.cpp,v $
  222.  * Revision 1000.3  2004/06/01 19:42:34  gouriano
  223.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.13
  224.  *
  225.  * Revision 1.13  2004/05/17 21:09:26  gorelenk
  226.  * Added include of PCH ncbi_pch.hpp
  227.  *
  228.  * Revision 1.12  2003/12/18 03:42:14  ucko
  229.  * Call peek() to force at least minimal blocking, since Readsome might
  230.  * not block at all and accepting 0-byte reads could lead to spinning.
  231.  *
  232.  * Revision 1.11  2003/11/21 19:59:55  lavr
  233.  * Buffer size decreased to 1/2 Meg, post-pushback seekg() test added
  234.  *
  235.  * Revision 1.10  2003/04/11 17:59:22  lavr
  236.  * Macro _STR(x) [mistakenly left empty] defined properly
  237.  *
  238.  * Revision 1.9  2003/03/25 22:14:36  lavr
  239.  * Take advantage of CStreamUtils::Readsome() instead of custom s_Read()
  240.  *
  241.  * Revision 1.8  2002/11/27 21:10:33  lavr
  242.  * Change Pushback() methods to be CStreamUtils', not standalone
  243.  *
  244.  * Revision 1.7  2002/07/16 15:08:34  lavr
  245.  * Use ANSI-compliant stringizing
  246.  *
  247.  * Revision 1.6  2002/04/16 18:52:15  ivanov
  248.  * Centralize threatment of assert() in tests.
  249.  * Added #include <test/test_assert.h>. CVS log moved to end of file.
  250.  *
  251.  * Revision 1.5  2002/02/05 21:45:19  lavr
  252.  * Included header files rearranged
  253.  *
  254.  * Revision 1.4  2002/02/05 16:06:41  lavr
  255.  * List of included header files revised; Use macro IOS_BASE instead of raw ios
  256.  *
  257.  * Revision 1.3  2002/02/04 20:23:40  lavr
  258.  * Long comment and workaround for MSVC putback()/unget() bug/feature
  259.  * Additional test for stream positioning during read back
  260.  *
  261.  * Revision 1.2  2002/01/30 20:07:13  lavr
  262.  * Verbose message about the difference, not just a position number
  263.  *
  264.  * Revision 1.1  2002/01/29 16:02:19  lavr
  265.  * Initial revision
  266.  *
  267.  * ==========================================================================
  268.  */