reSIProcate/rutil  9694
testLogger.cxx
Go to the documentation of this file.
00001 
00002 #include "rutil/Logger.hxx"
00003 #include "rutil/Data.hxx"
00004 #include "rutil/ThreadIf.hxx"
00005 #include "rutil/Timer.hxx"
00006 
00007 #include "TestSubsystemLogLevel.hxx"
00008 #include "rutil/WinLeakCheck.hxx"
00009 
00010 #ifdef WIN32
00011 #define usleep(x) Sleep(x/1000)
00012 #define sleep(x) Sleep(x*1000)
00013 #endif
00014 
00015 using namespace resip;
00016 using namespace std;
00017 
00018 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP
00019 
00020 
00021 class LogThread : public ThreadIf
00022 {
00023     public:
00024       LogThread(const Data& description, const Log::ThreadSetting& s,
00025                 Log::LocalLoggerId id = 0)
00026          : mDescription(description),
00027            mSetting(s),
00028            mId(id)
00029       {}
00030 
00031       void thread()
00032       {
00033          Log::setThreadSetting(mSetting);
00034          int reval = Log::setThreadLocalLogger(mId);
00035          (void)reval;   // make gcc4 happy
00036 //         InfoLog(<< "setThreadLocalLogger(" << mId << ") returned " << reval);
00037          while(!waitForShutdown(1000))
00038          {
00039             StackLog(<< mDescription << "  STACK");
00040             DebugLog(<< mDescription << "  DEBUG");
00041             InfoLog(<< mDescription << "  INFO");
00042          }
00043       }
00044    private:
00045       Data mDescription;
00046       Log::ThreadSetting mSetting;
00047       Log::LocalLoggerId mId;
00048 };
00049 
00050 int logsInCall()
00051 {
00052    InfoLog(<< "Got here?");
00053    return 17;
00054 }
00055 
00056 
00057 int debugLogsInCall()
00058 {
00059    DebugLog(<< "Got here?");
00060    return 17;
00061 }
00062 
00063 class TestExternalLogger : public ExternalLogger
00064 {
00065    public:
00066       virtual bool operator()(Log::Level level,
00067                               const Subsystem& subsystem, 
00068                               const Data& appName,
00069                               const char* file,
00070                               int line,
00071                               const Data& message,
00072                               const Data& messageWithHeaders)
00073       {
00074          cout << "From TestExternalLogger: " << message << endl;
00075          return true;         
00076       }
00077 };
00078 
00079 void
00080 testThreadLocalLoggers(const char *appname)
00081 {
00082    Log::initialize(Log::Cout, Log::Info, appname);
00083 
00084    InfoLog(<<"Going to test thread local loggers.");
00085    Noisy::outputLogMessages();
00086 
00087    Log::LocalLoggerId id1 = Log::localLoggerCreate(Log::File, Log::Info, "testLogger-local1.txt");
00088    Log::LocalLoggerId id2 = Log::localLoggerCreate(Log::File, Log::Info, "testLogger-local2.txt");
00089 
00090    LogThread serviceErr("service with wrong local logger Id",
00091                         Log::ThreadSetting(1, Log::Debug), id2+10);
00092 
00093    LogThread service0("global", Log::ThreadSetting(1, Log::Debug));
00094    LogThread service1a("local1----A", Log::ThreadSetting(1, Log::Debug), id1);
00095    LogThread service1b("local1-------B", Log::ThreadSetting(1, Log::Debug), id1);
00096    LogThread service2a("local2---------C", Log::ThreadSetting(1, Log::Debug), id2);
00097    LogThread service2b("local2-----------D", Log::ThreadSetting(1, Log::Debug), id2);
00098 
00099    service0.run();
00100    service1a.run();
00101    service1b.run();
00102    service2a.run();
00103    service2b.run();
00104 
00105    sleep(3);
00106 
00107    service0.shutdown();
00108    service1a.shutdown();
00109    service1b.shutdown();
00110    service2a.shutdown();
00111    service2b.shutdown();
00112 
00113    service0.join();
00114    service1a.join();
00115    service1b.join();
00116    service2a.join();
00117    service2b.join();
00118 
00119    int retval = Log::localLoggerRemove(id1);
00120    if (retval > 0)
00121    {
00122       std::cerr << "Local logger 1 hasn't been cleaned up correctly! "
00123                    "Log::localLoggerRemove() return code is " << retval << std::endl;
00124    }
00125    retval = Log::localLoggerRemove(id2);
00126    if (retval > 0)
00127    {
00128       std::cerr << "Local logger 2 hasn't been cleaned up correctly! "
00129                    "Log::localLoggerRemove() return code is " << retval << std::endl;
00130    }
00131 }
00132 
00133 int
00134 main(int argc, char* argv[])
00135 {
00136 #if defined(WIN32) && defined(_DEBUG) && defined(LEAK_CHECK) 
00137    FindMemoryLeaks fml;
00138 #endif
00139 
00140    CritLog(<< "logging before initializing is ok");
00141 
00142    Log::initialize(Log::Cout, Log::Info, argv[0]);
00143 
00144    InfoLog(<<"Subsystem level for TEST subsystem, not level set, global is info.");
00145    Noisy::outputLogMessages();
00146    Log::setLevel(Log::Debug, Subsystem::TEST);
00147    InfoLog(<<"Subsystem level for TEST subsystem, TEST set to Debug, global is info.");
00148    Noisy::outputLogMessages();
00149    Log::setLevel(Log::Crit, Subsystem::TEST);
00150    InfoLog(<<"Subsystem level for TEST subsystem, TEST set to Crit, global is info.");
00151    Noisy::outputLogMessages();
00152 
00153    DebugLog(<<"This should not appear.");
00154    InfoLog(<<"This should appear.");
00155 
00156    LogThread service1a("service1----A", Log::ThreadSetting(1, Log::Debug));
00157    LogThread service1b("service1-------B", Log::ThreadSetting(1, Log::Debug));
00158    LogThread service1c("service1---------C", Log::ThreadSetting(1, Log::Debug));
00159 
00160    LogThread service2a("service2-----------A", Log::ThreadSetting(2, Log::Debug));
00161    LogThread service2b("service2------------------B", Log::ThreadSetting(2, Log::Err));
00162 
00163    service1a.run();
00164    service1b.run();
00165    service1c.run();
00166    service2a.run();
00167    service2b.run();
00168 
00169    sleep(2);
00170 
00171    InfoLog(<<"Setting service 1 to INFO\n");
00172    Log::setServiceLevel(1, Log::Info);
00173    sleep(2);
00174 
00175    InfoLog(<<"Setting service 1 to CRIT\n");
00176    Log::setServiceLevel(1, Log::Crit);
00177    sleep(2);
00178 
00179    InfoLog(<<"Setting service 2 to STACK\n");
00180    Log::setServiceLevel(2, Log::Stack);
00181    sleep(2);
00182 
00183    InfoLog(<<"Setting service 1 to DEBUG\n");
00184    Log::setServiceLevel(1, Log::Debug);
00185    sleep(2);
00186 
00187    DebugLog(<<"This should still not appear.");
00188    InfoLog(<<"This should still appear.");
00189 
00190    InfoLog(<<"Log will now be written to testLoggerOut.txt.");
00191 
00192    Log::initialize(Log::File, Log::Info, argv[0], "testLoggerOut.txt");  
00193    InfoLog(<<"This should be in the file");
00194    sleep(2);
00195    
00196    Log::initialize(Log::Cout, Log::Info, argv[0]);
00197    InfoLog(<<"This should appear-back to Cout");
00198    sleep(2);   
00199 
00200    TestExternalLogger tel;
00201    Log::initialize(Log::OnlyExternal, Log::Info, argv[0], tel);
00202    InfoLog(<<"This should appear-back in cout through the extenal logger, and nowhere else");
00203    sleep(2);   
00204 
00205    service1a.shutdown();
00206    service1b.shutdown();
00207    service1c.shutdown();
00208    service2a.shutdown();
00209    service2b.shutdown();
00210 
00211    service1a.join();
00212    service1b.join();
00213    service1c.join();
00214    service2a.join();
00215    service2b.join();
00216    
00217    Log::initialize(Log::Cout, Log::Info, argv[0]);
00218    InfoLog(<<"This should appear-back to Cout");
00219    sleep(2);   
00220 
00221    Log::setLevel(Log::Info);
00222 
00223    if (false)
00224    {
00225       UInt64 start = Timer::getTimeMs();
00226       for (int i = 0; i < 10000; i++)
00227       {
00228          InfoLog(<< "string");
00229       }
00230       cerr << "Info Took: " << Timer::getTimeMs() - start << endl;
00231    }
00232 
00233    if (false)
00234    {
00235       UInt64 start = Timer::getTimeMs();
00236       for (int i = 0; i < 10000; i++)
00237       {
00238          DebugLog(<< "string");
00239       }
00240       cerr << "Debug Took: " << Timer::getTimeMs() - start << endl;
00241    }
00242 
00243    InfoLog(<< "Recursive debug: " << debugLogsInCall());
00244    DebugLog(<< "Recursive non-debug OK: " << logsInCall());
00245 
00246    InfoLog(<< "Recursive non-debug OK!: " << logsInCall());
00247 
00248    cout << endl;
00249    testThreadLocalLoggers(argv[0]);
00250 
00251    return 0;
00252 }
00253 
00254 /* ====================================================================
00255  * The Vovida Software License, Version 1.0 
00256  * 
00257  * Copyright (c) 2000 Vovida Networks, Inc.  All rights reserved.
00258  * 
00259  * Redistribution and use in source and binary forms, with or without
00260  * modification, are permitted provided that the following conditions
00261  * are met:
00262  * 
00263  * 1. Redistributions of source code must retain the above copyright
00264  *    notice, this list of conditions and the following disclaimer.
00265  * 
00266  * 2. Redistributions in binary form must reproduce the above copyright
00267  *    notice, this list of conditions and the following disclaimer in
00268  *    the documentation and/or other materials provided with the
00269  *    distribution.
00270  * 
00271  * 3. The names "VOCAL", "Vovida Open Communication Application Library",
00272  *    and "Vovida Open Communication Application Library (VOCAL)" must
00273  *    not be used to endorse or promote products derived from this
00274  *    software without prior written permission. For written
00275  *    permission, please contact vocal@vovida.org.
00276  *
00277  * 4. Products derived from this software may not be called "VOCAL", nor
00278  *    may "VOCAL" appear in their name, without prior written
00279  *    permission of Vovida Networks, Inc.
00280  * 
00281  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
00282  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00283  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
00284  * NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL VOVIDA
00285  * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
00286  * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
00287  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00288  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00289  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
00290  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00291  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00292  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
00293  * DAMAGE.
00294  * 
00295  * ====================================================================
00296  * 
00297  * This software consists of voluntary contributions made by Vovida
00298  * Networks, Inc. and many individuals on behalf of Vovida Networks,
00299  * Inc.  For more information on Vovida Networks, Inc., please see
00300  * <http://www.vovida.org/>.
00301  *
00302  */
00303