netrq/test/test1.cpp

Go to the documentation of this file.
00001 /*
00002  * test1.cpp
00003  *
00004  * Copyright (C) 2009  Thomas A. Vaughan
00005  * All rights reserved.
00006  *
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions are met:
00010  *     * Redistributions of source code must retain the above copyright
00011  *       notice, this list of conditions and the following disclaimer.
00012  *     * Redistributions in binary form must reproduce the above copyright
00013  *       notice, this list of conditions and the following disclaimer in the
00014  *       documentation and/or other materials provided with the distribution.
00015  *     * Neither the name of the <organization> nor the
00016  *       names of its contributors may be used to endorse or promote products
00017  *       derived from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THOMAS A. VAUGHAN ''AS IS'' AND ANY
00020  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00021  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00022  * DISCLAIMED. IN NO EVENT SHALL THOMAS A. VAUGHAN BE LIABLE FOR ANY
00023  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00024  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00025  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00026  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00027  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00028  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00029  *
00030  * Quick tests for the netrq (network request queue) library.
00031  */
00032 
00033 // includes --------------------------------------------------------------------
00034 #include "netrq/netrq.h"                // include library header first
00035 
00036 #include <iostream>
00037 
00038 #include "common/wave_ex.h"
00039 #include "perf/perf.h"
00040 
00041 
00042 // statics ---------------------------------------------------------------------
00043 static const int s_maxByteSize          = 255;
00044 
00045 static char s_testMessage[s_maxByteSize];
00046 
00047 
00048 ////////////////////////////////////////////////////////////////////////////////
00049 //
00050 //      static helper methods
00051 //
00052 ////////////////////////////////////////////////////////////////////////////////
00053 
00054 class TestRequest : public netrq::Request {
00055 public:
00056         virtual ~TestRequest(void) throw() { }
00057 
00058         // netrq::Request class interface methods ------------------------------
00059         const char * getId(void) const throw() {
00060                         return m_id.c_str();
00061                 }
00062         int getMaxBytes(void) const throw() {
00063                         // our message size plus packlet header
00064                         return m_nBytes + 2;
00065                 }
00066         void write(IO xdrbuf::Output * output) {
00067                         ASSERT(output, "null");
00068                         output->addStringPacklet('s', s_testMessage, m_nBytes);
00069                 }
00070 
00071         // public factory methods ----------------------------------------------
00072         static smart_ptr<TestRequest> create(IN int nBytes) {
00073                         ASSERT(nBytes > 0, "Bad byte count: %d", nBytes);
00074                         ASSERT(nBytes < s_maxByteSize, "too many bytes: %d",
00075                             nBytes);
00076                         smart_ptr<TestRequest> local = new TestRequest;
00077                         ASSERT(local, "out of memory");
00078                         local->m_nBytes = nBytes;
00079 
00080                         char buffer[32];
00081                         sprintf(buffer, "id-%d", rand() % 128);
00082                         local->m_id = buffer;
00083 
00084                         return local;
00085                 }
00086 
00087 private:
00088         std::string     m_id;
00089         int             m_nBytes;
00090 };
00091 
00092 
00093 
00094 bool
00095 addRandomRequest
00096 (
00097 IO netrq::Queue * queue
00098 )
00099 {
00100         ASSERT(queue, "null");
00101 
00102         int nBytes = 32 + (rand() % (s_maxByteSize - 33));
00103         smart_ptr<netrq::Request> request = TestRequest::create(nBytes);
00104         ASSERT(request, "null");
00105 
00106         dword_t clock = 1 + (rand() % 32);
00107         netrq::Queue::eInsertResult result = queue->addRequest(clock, request);
00108         if (netrq::Queue::eQueue_Failed_CurrentEntryHasLaterClock == result) {
00109         //      DPRINTF("Failed to add request--forcing deletion of existing");
00110                 const char * id = request->getId();
00111                 if (!queue->removeRequest(id)) {
00112                         WAVE_EX(wex);
00113                         wex << "Failed to remove existing request?";
00114                 }
00115                 result = queue->addRequest(clock, request);
00116                 if (netrq::Queue::eQueue_Success != result) {
00117                         WAVE_EX(wex);
00118                         wex << "Failed to re-insert after deleting colliding entry";
00119                 }
00120 
00121                 return true;
00122         }
00123 
00124         return false;   // no removals required
00125 }
00126 
00127 
00128 
00129 void
00130 doTest1
00131 (
00132 IN int bufSize,
00133 IN int nMessages,
00134 IN int nLoops
00135 )
00136 {
00137         ASSERT(bufSize > 0, "Bad output buffer size: %d", bufSize);
00138         ASSERT(nMessages > 0, "Bad message count: %d", nMessages);
00139         ASSERT(nLoops > 0, "Bad loop count: %d", nLoops);
00140 
00141         // first, create output buffer
00142         smart_ptr<xdrbuf::Output> output = xdrbuf::Output::create(bufSize);
00143         ASSERT(output, "null");
00144 
00145         // next, create and populate network queue
00146         int removalCount = 0;
00147         smart_ptr<netrq::Queue> queue = netrq::Queue::create();
00148         ASSERT(queue, "null");
00149         for (int i = 0; i < nMessages; ++i) {
00150                 if (addRandomRequest(queue)) {
00151                         ++removalCount;
00152                 }
00153         }
00154         DPRINTF("Had to remove %d requests due to collisions", removalCount);
00155         DPRINTF("Total queue size: %d requests", queue->size());
00156 
00157         // finally, loop and send
00158         dword_t clock = 1;
00159         for (int i = 0; i < nLoops; ++i) {
00160                 output->clear();
00161                 int nSent = netrq::sendMessagesFromQueue(output, clock, queue);
00162                 if (nSent) {
00163                         DPRINTF("Clock %lu: sent %d messages", (long) clock,
00164                             nSent);
00165                 }
00166                 ++clock;
00167         }
00168 }
00169 
00170 
00171 
00172 ////////////////////////////////////////////////////////////////////////////////
00173 //
00174 //      entry point
00175 //
00176 ////////////////////////////////////////////////////////////////////////////////
00177 
00178 int
00179 main
00180 (
00181 IN int argc,
00182 IN const char * argv[]
00183 )
00184 {
00185         int retval = 0;
00186         try {
00187                 perf::Timer timer("overall timer");
00188 
00189                 // set up the test buffer message
00190                 for (int i = 0; i < s_maxByteSize; ++i) {
00191                         s_testMessage[i] = 'a';
00192                 }
00193                 s_testMessage[s_maxByteSize - 1] = 0;
00194 
00195                 // run tests
00196                 doTest1(500, 200, 200);
00197                 doTest1(255, 200, 200);
00198                 doTest1(8192, 2048, 200);
00199         } catch (std::exception& e) {
00200                 DPRINTF("Exception: %s", e.what());
00201                 retval = 1;
00202         } catch (...) {
00203                 DPRINTF("Unknown exception!");
00204                 retval = 2;
00205         }
00206         perf::dumpTimingSummary(std::cerr);
00207 
00208         return retval;
00209 }
00210