reSIProcate/stack  9694
testHash.cxx
Go to the documentation of this file.
00001 #include <iostream>
00002 #ifndef WIN32
00003 #include <unistd.h>
00004 #endif
00005 
00006 #include <limits.h>
00007 #include <signal.h>
00008 #include <sys/fcntl.h>
00009 #include "rutil/Logger.hxx"
00010 #include "resip/stack/HeaderTypes.hxx"
00011 #include "resip/stack/ParameterTypeEnums.hxx"
00012 #include "resip/stack/ParameterTypes.hxx"
00013 #include "resip/stack/MethodTypes.hxx"
00014 
00015 using namespace resip;
00016 using namespace std;
00017 
00018 #define RESIPROCATE_SUBSYSTEM resip::Subsystem::TEST
00019 
00020 volatile bool signalled = false;
00021 
00022 void tick(int sig)
00023 {
00024    signalled = true;
00025 }
00026 
00027 
00028 static 
00029 struct {
00030       char * keyword;
00031       Headers::Type type;
00032       int len;
00033 } headerInfo[(int)(Headers::MAX_HEADERS)];
00034 
00035 
00036 unsigned int  InitHeaderInfo()
00037 {
00038    int i = static_cast<int>(Headers::UNKNOWN)+1;
00039    int max  = static_cast<int>(Headers::MAX_HEADERS);
00040    
00041    for( ;
00042        i < max;
00043        ++i)
00044    {
00045        Headers::Type t = static_cast<Headers::Type>(i);
00046        
00047       char* p = strdup(resip::Headers::getHeaderName(i).c_str());
00048       
00049       headerInfo[i].len = Headers::getHeaderName(i).size();
00050       headerInfo[i].keyword = p;
00051       headerInfo[i].type = t;
00052       
00053       DebugLog(<< headerInfo[i].keyword << " ["
00054                << headerInfo[i].type <<"]");
00055    }
00056 
00057    return i;
00058    
00059 }
00060 
00061 bool checkMethods()
00062 {
00063     int i = static_cast<int>(resip::UNKNOWN)+1;
00064     int max = static_cast<int>(resip::MAX_METHODS);
00065     bool failure = false;
00066     for( ; i < max ; ++i)
00067     {
00068         MethodTypes t = static_cast<MethodTypes>(i);
00069         const Data& d(resip::getMethodName(t));
00070         MethodTypes nt = resip::getMethodType(d.data(),d.size());
00071         bool ok = nt == t;
00072         // DebugLog(<<resip::MethodNames[t]<<" : " << (ok ? "OK":"FAIL"));
00073         DebugLog(<< (ok ? "   " : "***" ) << ' '
00074                  << t << ' ' << resip::getMethodName(t) 
00075                  << '(' << d << ')'
00076                  << " -> " 
00077                  << nt << ' ' << resip::getMethodName(nt));
00078         // if (!ok) ErrLog(<<resip::getMethodName(t) << " : HASH FAILURE");
00079         failure |= !ok;
00080     }
00081     return !failure;
00082 }
00083 
00084 bool
00085 checkParameters()
00086 {
00087     int i = static_cast<int>(ParameterTypes::UNKNOWN)+1;
00088     int max = static_cast<int>(ParameterTypes::MAX_PARAMETER);
00089     bool failure = false;
00090     
00091     for( ; i < max ; ++i)
00092     {
00093         ParameterTypes::Type t = static_cast<ParameterTypes::Type>(i);
00094         Data& d = ParameterTypes::ParameterNames[t];
00095         bool ok = ParameterTypes::getType(d.data(),d.size()) == t;
00096         DebugLog(<<ParameterTypes::ParameterNames[t]<<" : " << (ok?"OK":"FAIL"));
00097         failure |= !ok;
00098     }
00099     return !failure;
00100 }
00101 
00102 unsigned short randomUShort()
00103 {
00104    static int fd = 0;
00105    static bool init = false;
00106    if (!init)
00107    {
00108       fd = open("/dev/urandom",O_RDONLY);
00109       if (fd < 0)
00110       {
00111  cerr << "randomShort(): unable to open /dev/urandom -- degraded mode"
00112       << endl;
00113       }
00114       init = true;
00115    }
00116    if (init && fd >= 0)
00117    {
00118       unsigned short r;
00119       int n = 0;
00120       if ((n=read(fd,&r,sizeof(r))) == sizeof(r))
00121       {
00122  return r;
00123       }
00124    }
00125    // degraded mode
00126    return (unsigned short)((USHRT_MAX + 1.0) * rand() / (RAND_MAX+1.0));
00127 }
00128 
00129 
00130 int
00131 main()
00132 {
00133    bool failure = false;
00134    
00135    register unsigned int i = 0;
00136 
00137    // Load up the main table
00138    unsigned short nKeywords =    InitHeaderInfo();
00139    
00140 
00141    // Verify that the hash function works.
00142    InfoLog(<<"Checking that hash function works for all known headers");
00143    for(i=0;i<nKeywords;i++)
00144    {
00145       Headers::Type t = Headers::getType(headerInfo[i].keyword,
00146                                          headerInfo[i].len);
00147       bool ok = headerInfo[i].type == t;
00148       
00149       InfoLog(<< headerInfo[i].keyword << " " << (ok?"OK":"FAIL"));
00150       if (!ok)
00151       {
00152          ErrLog(<<headerInfo[i].keyword << "["
00153                 <<headerInfo[i].type << "] hashed to "
00154                 << t << " ["
00155                 << Headers::getHeaderName(i) << "]");
00156       }
00157       
00158    }
00159    
00160    InfoLog(<<"Checking methods.");
00161 
00162    bool p = checkMethods();
00163    
00164    InfoLog(<<" methods: " << (p?"OK":"FAIL"));
00165 
00166    p = checkParameters();
00167 
00168    InfoLog(<<" parameters: " << (p?"OK":"FAIL"));
00169    
00170 
00171 #if defined (TIME_HASH_TEST)   
00172    int randomList[100*1024];
00173 
00174    // Make a large random list so we don't take a hit with 
00175    // random() calcs during the hash.
00176    unsigned int nRandom = sizeof(randomList)/sizeof(*randomList);
00177 
00178    InfoLog(<< "Pre-loading random list of " << nRandom << " entries");
00179    
00180    for(i = 0; i < nRandom ;  i++)
00181    {
00182       short r = randomUShort()%nKeywords;
00183       randomList[i] = r;
00184    }
00185    
00186    i=0;
00187    InfoLog(<<"Starting timing loop");
00188 
00189    register int totalTime=30;
00190    register int interval=5;
00191    register int timer=totalTime;
00192    register int elapsed=0;
00193    
00194    signal(SIGALRM, tick);
00195    register unsigned long long counter = 0;
00196 
00197    assert(totalTime/interval*interval == totalTime);
00198    
00199    while (timer>0)
00200    {
00201       alarm(interval);
00202       while (!signalled)
00203       {
00204 
00205          volatile register Headers::Type hdr = 
00206             Headers::getType(headerInfo[randomList[i]].keyword,
00207                              headerInfo[randomList[i]].len);
00208 
00209          counter++;
00210          i++;
00211          if (i >= nRandom) i = 0;
00212       }
00213       timer-=interval;
00214       elapsed+=interval;
00215       InfoLog(<< timer <<" sec rem: " 
00216               << counter << " hashes "
00217               << counter/elapsed << " h/sec");
00218       signalled=false;
00219       
00220    }
00221 #endif
00222    if (failure) CritLog(<<"Problems in hashes. See above");
00223    return failure?1:0;
00224    
00225 }
00226 
00227 
00228 /* ====================================================================
00229  * The Vovida Software License, Version 1.0 
00230  * 
00231  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00232  * 
00233  * Redistribution and use in source and binary forms, with or without
00234  * modification, are permitted provided that the following conditions
00235  * are met:
00236  * 
00237  * 1. Redistributions of source code must retain the above copyright
00238  *    notice, this list of conditions and the following disclaimer.
00239  * 
00240  * 2. Redistributions in binary form must reproduce the above copyright
00241  *    notice, this list of conditions and the following disclaimer in
00242  *    the documentation and/or other materials provided with the
00243  *    distribution.
00244  * 
00245  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00246  *    and "Vovida Open Communication Application Library (VOCAL)" must
00247  *    not be used to endorse or promote products derived from this
00248  *    software without prior written permission. For written
00249  *    permission, please contact vocal@vovida.org.
00250  *
00251  * 4. Products derived from this software may not be called "VOCAL", nor
00252  *    may "VOCAL" appear in their name, without prior written
00253  *    permission of Vovida Networks, Inc.
00254  * 
00255  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00256  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00257  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00258  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00259  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00260  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00261  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00262  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00263  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00264  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00265  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00266  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00267  * DAMAGE.
00268  * 
00269  * ====================================================================
00270  * 
00271  * This software consists of voluntary contributions made by Vovida
00272  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00273  * Inc.  For more information on Vovida Networks, Inc., please see
00274  * <http://www.vovida.org/>.
00275  *
00276  */