llerror_tut.cpp

Go to the documentation of this file.
00001 
00033 #include "linden_common.h"
00034 #include "llerror.h"
00035 
00036 namespace
00037 {
00038         void test_that_error_h_includes_enough_things_to_compile_a_message()
00039         {
00040                 llinfos << "!" << llendl;
00041         }
00042 }
00043 
00044 #include <tut/tut.h>
00045 #include "lltut.h"
00046 
00047 #include <vector>
00048 
00049 #include "llerrorcontrol.h"
00050 #include "llsd.h"
00051 
00052 namespace
00053 {
00054         static bool fatalWasCalled;
00055         void fatalCall(const std::string&) { fatalWasCalled = true; }
00056         
00057         class TestRecorder : public LLError::Recorder
00058         {
00059         public:
00060                 TestRecorder() : mWantsTime(false) { }
00061                 ~TestRecorder() { LLError::removeRecorder(this); }
00062                 
00063                 void recordMessage(LLError::ELevel level,
00064                                                         const std::string& message)
00065                 {
00066                         mMessages.push_back(message);
00067                 }
00068                 
00069                 int countMessages()                     { return (int) mMessages.size(); }
00070                 void clearMessages()            { mMessages.clear(); }
00071                 
00072                 void setWantsTime(bool t)       { mWantsTime = t; }
00073                 bool wantsTime()                        { return mWantsTime; }
00074 
00075                 std::string message(int n)
00076                 {
00077                         std::ostringstream test_name;
00078                         test_name << "testing message " << n << ", not enough messages";
00079 
00080                         tut::ensure(test_name.str(), n < countMessages());
00081                         return mMessages[n];
00082                 }
00083                 
00084         private:
00085                 typedef std::vector<std::string> MessageVector;
00086                 MessageVector mMessages;
00087                 
00088                 bool mWantsTime;
00089         };
00090 }
00091         
00092 namespace tut
00093 {
00094         struct ErrorTestData
00095         {
00096                 TestRecorder mRecorder;
00097                 LLError::Settings* mPriorErrorSettings;
00098                 
00099                 ErrorTestData()
00100                 {
00101                         fatalWasCalled = false;
00102                         
00103                         mPriorErrorSettings = LLError::saveAndResetSettings();
00104                         LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
00105                         LLError::setFatalFunction(fatalCall);
00106                         LLError::addRecorder(&mRecorder);
00107                 }
00108                 
00109                 ~ErrorTestData()
00110                 {
00111                         LLError::removeRecorder(&mRecorder);
00112                         LLError::restoreSettings(mPriorErrorSettings);
00113                 }
00114                 
00115                 void ensure_message_count(int expectedCount)
00116                 {
00117                         ensure_equals("message count", mRecorder.countMessages(), expectedCount);
00118                 }
00119 
00120                 void ensure_message_contains(int n, const std::string& expectedText)
00121                 {
00122                         std::ostringstream test_name;
00123                         test_name << "testing message " << n;
00124 
00125                         ensure_contains(test_name.str(), mRecorder.message(n), expectedText);
00126                 }
00127 
00128                 void ensure_message_does_not_contain(int n, const std::string& expectedText)
00129                 {
00130                         std::ostringstream test_name;
00131                         test_name << "testing message " << n;
00132 
00133                         ensure_does_not_contain(test_name.str(), mRecorder.message(n), expectedText);
00134                 }
00135         };
00136         
00137         typedef test_group<ErrorTestData>       ErrorTestGroup;
00138         typedef ErrorTestGroup::object          ErrorTestObject;
00139         
00140         ErrorTestGroup errorTestGroup("error");
00141         
00142         template<> template<>
00143         void ErrorTestObject::test<1>()
00144                 // basic test of output
00145         {
00146                 llinfos << "test" << llendl;
00147                 llinfos << "bob" << llendl;
00148                 
00149                 ensure_message_contains(0, "test");
00150                 ensure_message_contains(1, "bob");
00151         }
00152 }
00153 
00154 namespace
00155 {
00156         void writeSome()
00157         {
00158                 lldebugs << "one" << llendl;
00159                 llinfos << "two" << llendl;
00160                 llwarns << "three" << llendl;
00161                 llerrs << "four" << llendl;
00162                         // fatal messages write out and addtional "error" message
00163         }
00164 };
00165 
00166 namespace tut
00167 {       
00168         template<> template<>
00169         void ErrorTestObject::test<2>()
00170                 // messages are filtered based on default level
00171         {
00172                 LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
00173                 writeSome();
00174                 ensure_message_contains(0, "one");
00175                 ensure_message_contains(1, "two");
00176                 ensure_message_contains(2, "three");
00177                 ensure_message_contains(3, "error");
00178                 ensure_message_contains(4, "four");
00179                 ensure_message_count(5);
00180         
00181                 LLError::setDefaultLevel(LLError::LEVEL_INFO);
00182                 writeSome();
00183                 ensure_message_contains(5, "two");
00184                 ensure_message_contains(6, "three");
00185                 ensure_message_contains(7, "error");
00186                 ensure_message_contains(8, "four");
00187                 ensure_message_count(9);
00188                 
00189                 LLError::setDefaultLevel(LLError::LEVEL_WARN);
00190                 writeSome();
00191                 ensure_message_contains(9, "three");
00192                 ensure_message_contains(10, "error");
00193                 ensure_message_contains(11, "four");
00194                 ensure_message_count(12);
00195                 
00196                 LLError::setDefaultLevel(LLError::LEVEL_ERROR);
00197                 writeSome();
00198                 ensure_message_contains(12, "error");
00199                 ensure_message_contains(13, "four");
00200                 ensure_message_count(14);
00201                 
00202                 LLError::setDefaultLevel(LLError::LEVEL_NONE);
00203                 writeSome();
00204                 ensure_message_count(14);
00205         }
00206 
00207         template<> template<>
00208         void ErrorTestObject::test<3>()
00209                 // error type string in output
00210         {
00211                 writeSome();
00212                 ensure_message_contains(0, "DEBUG: ");
00213                 ensure_message_contains(1, "INFO: ");
00214                 ensure_message_contains(2, "WARNING: ");
00215                 ensure_message_does_not_contain(3, "ERROR");
00216                 ensure_message_contains(4, "ERROR: ");
00217                 ensure_message_count(5);
00218         }
00219 
00220         template<> template<>
00221         void ErrorTestObject::test<4>()
00222                 // file abbreviation
00223         {
00224                 std::string thisFile = __FILE__;
00225                 std::string abbreviateFile = LLError::abbreviateFile(thisFile);
00226                 
00227                 ensure_ends_with("file name abbreviation",
00228                         abbreviateFile,
00229                         "test/llerror_tut.cpp"
00230                         );
00231                 ensure_does_not_contain("file name abbreviation",
00232                         abbreviateFile, "indra");
00233                         
00234                 std::string someFile =
00235 #if LL_WINDOWS
00236                         "C:/amy/bob/cam.cpp"
00237 #else
00238                         "/amy/bob/cam.cpp"
00239 #endif
00240                         ;
00241                 std::string someAbbreviation = LLError::abbreviateFile(someFile);
00242                 
00243                 ensure_equals("non-indra file abbreviation",
00244                         someAbbreviation, someFile);
00245         }
00246 }
00247         
00248 namespace
00249 {
00250         std::string locationString(int line)
00251         {
00252                 std::ostringstream location;
00253                 location << LLError::abbreviateFile(__FILE__)
00254                                  << "(" << line << ") : ";
00255                                  
00256                 return location.str();
00257         }
00258         
00259         std::string writeReturningLocation()
00260         {
00261                 llinfos << "apple" << llendl;   int this_line = __LINE__;
00262                 return locationString(this_line);
00263         }
00264         
00265         std::string writeReturningLocationAndFunction()
00266         {
00267                 llinfos << "apple" << llendl;   int this_line = __LINE__;
00268                 return locationString(this_line) + __FUNCTION__;
00269         }
00270         
00271         std::string errorReturningLocation()
00272         {
00273                 llerrs << "die" << llendl;      int this_line = __LINE__;
00274                 return locationString(this_line);
00275         }
00276 }
00277 
00278 namespace tut
00279 {       
00280         template<> template<>
00281         void ErrorTestObject::test<5>()
00282                 // file and line information in log messages
00283         {
00284                 std::string location = writeReturningLocation();
00285                         // expecting default to not print location information
00286                 
00287                 LLError::setPrintLocation(true);
00288                 writeReturningLocation();
00289                 
00290                 LLError::setPrintLocation(false);
00291                 writeReturningLocation();
00292                 
00293                 ensure_message_does_not_contain(0, location);
00294                 ensure_message_contains(1, location);
00295                 ensure_message_does_not_contain(2, location);
00296         }
00297 }
00298 
00299 /* The following helper functions and class members all log a simple message
00300         from some particular function scope.  Each function takes a bool argument
00301         that indicates if it should log its own name or not (in the manner that
00302         existing log messages often do.)  The functions all return their C++
00303         name so that test can be substantial mechanized.
00304  */
00305  
00306 std::string logFromGlobal(bool id)
00307 {
00308         llinfos << (id ? "logFromGlobal: " : "") << "hi" << llendl;
00309         return "logFromGlobal";
00310 }
00311 
00312 static std::string logFromStatic(bool id)
00313 {
00314         llinfos << (id ? "logFromStatic: " : "") << "hi" << llendl;
00315         return "logFromStatic";
00316 }
00317 
00318 namespace
00319 {
00320         std::string logFromAnon(bool id)
00321         {
00322                 llinfos << (id ? "logFromAnon: " : "") << "hi" << llendl;
00323                 return "logFromAnon";
00324         }
00325 }
00326 
00327 namespace Foo {
00328         std::string logFromNamespace(bool id)
00329         {
00330                 llinfos << (id ? "Foo::logFromNamespace: " : "") << "hi" << llendl;
00331                 //return "Foo::logFromNamespace";
00332                         // there is no standard way to get the namespace name, hence
00333                         // we won't be testing for it
00334                 return "logFromNamespace";
00335         }
00336 }
00337 
00338 namespace
00339 {
00340         class ClassWithNoLogType {
00341         public:
00342                 std::string logFromMember(bool id)
00343                 {
00344                         llinfos << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << llendl;
00345                         return "ClassWithNoLogType::logFromMember";
00346                 }
00347                 static std::string logFromStatic(bool id)
00348                 {
00349                         llinfos << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << llendl;
00350                         return "ClassWithNoLogType::logFromStatic";
00351                 }
00352         };
00353         
00354         class ClassWithLogType {
00355                 LOG_CLASS(ClassWithLogType);
00356         public:
00357                 std::string logFromMember(bool id)
00358                 {
00359                         llinfos << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << llendl;
00360                         return "ClassWithLogType::logFromMember";
00361                 }
00362                 static std::string logFromStatic(bool id)
00363                 {
00364                         llinfos << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << llendl;
00365                         return "ClassWithLogType::logFromStatic";
00366                 }
00367         };
00368         
00369         std::string logFromNamespace(bool id) { return Foo::logFromNamespace(id); }
00370         std::string logFromClassWithNoLogTypeMember(bool id) { ClassWithNoLogType c; return c.logFromMember(id); }
00371         std::string logFromClassWithNoLogTypeStatic(bool id) { return ClassWithNoLogType::logFromStatic(id); }
00372         std::string logFromClassWithLogTypeMember(bool id) { ClassWithLogType c; return c.logFromMember(id); }
00373         std::string logFromClassWithLogTypeStatic(bool id) { return ClassWithLogType::logFromStatic(id); }
00374         
00375         void ensure_has_once(const std::string& message,
00376                 const std::string& actual, const std::string& expected)
00377         {
00378                 std::string::size_type n1 = actual.find(expected);
00379                 std::string::size_type n2 = std::string::npos;
00380                 if (n1 != std::string::npos)
00381                 {
00382                         n2 = std::string(actual, n1 + expected.size()).find(expected);
00383                 }
00384                 
00385                 if (n1 == std::string::npos  ||  n2 != std::string::npos)
00386                 {
00387                         std::stringstream ss;
00388                         ss << message << ": " << "expected to find one copy of " << expected
00389                                 << " in actual " << actual;
00390                         throw tut::failure(ss.str().c_str());
00391                 }
00392         }
00393         
00394         typedef std::string (*LogFromFunction)(bool);
00395         void testLogNameOnce(TestRecorder& recorder, LogFromFunction f,
00396                 const std::string& class_name = "")
00397         {
00398                 recorder.clearMessages();
00399                 std::string name = f(false);
00400                 f(true);
00401                 
00402                 std::string messageWithoutName = recorder.message(0);
00403                 std::string messageWithName = recorder.message(1);
00404                 
00405                 ensure_has_once(name + " logged without name",
00406                         messageWithoutName, name);
00407                 ensure_has_once(name + " logged with name",
00408                         messageWithName, name);
00409 
00410                 if (!class_name.empty())
00411                 {
00412                         ensure_has_once(name + "logged without name",
00413                                 messageWithoutName, class_name);
00414                         ensure_has_once(name + "logged with name",
00415                                 messageWithName, class_name);
00416                 }
00417         }
00418 }
00419 
00420 namespace tut
00421 {
00422         template<> template<>
00423                 //      class/function information in output
00424         void ErrorTestObject::test<6>()
00425         {
00426                 testLogNameOnce(mRecorder, logFromGlobal);
00427                 testLogNameOnce(mRecorder, logFromStatic);
00428                 testLogNameOnce(mRecorder, logFromAnon);
00429                 testLogNameOnce(mRecorder, logFromNamespace);
00430                 //testLogNameOnce(mRecorder, logFromClassWithNoLogTypeMember, "ClassWithNoLogType");
00431                 //testLogNameOnce(mRecorder, logFromClassWithNoLogTypeStatic, "ClassWithNoLogType");
00432                         // XXX: figure out what the exepcted response is for these
00433                 testLogNameOnce(mRecorder, logFromClassWithLogTypeMember, "ClassWithLogType");
00434                 testLogNameOnce(mRecorder, logFromClassWithLogTypeStatic, "ClassWithLogType");
00435         }
00436 }
00437 
00438 namespace
00439 {
00440         std::string innerLogger()
00441         {
00442                 llinfos << "inside" << llendl;
00443                 return "moo";
00444         }
00445         
00446         std::string outerLogger()
00447         {
00448                 llinfos << "outside(" << innerLogger() << ")" << llendl;
00449                 return "bar";
00450         }
00451         
00452         void uberLogger()
00453         {
00454                 llinfos << "uber(" << outerLogger() << "," << innerLogger() << ")" << llendl;
00455         }
00456         
00457         class LogWhileLogging
00458         {
00459         public:
00460                 void print(std::ostream& out) const
00461                 {
00462                         llinfos << "logging" << llendl;
00463                         out << "baz";
00464                 }
00465         };
00466 
00467         std::ostream& operator<<(std::ostream& out, const LogWhileLogging& l)
00468                 { l.print(out); return out; }
00469 
00470         void metaLogger()
00471         {
00472                 LogWhileLogging l;
00473                 llinfos << "meta(" << l << ")" << llendl;
00474         }
00475         
00476 }
00477 
00478 namespace tut
00479 {                       
00480         template<> template<>
00481                 // handle nested logging
00482         void ErrorTestObject::test<7>()
00483         {
00484                 outerLogger();
00485                 ensure_message_contains(0, "inside");
00486                 ensure_message_contains(1, "outside(moo)");
00487                 ensure_message_count(2);
00488                 
00489                 uberLogger();
00490                 ensure_message_contains(2, "inside");
00491                 ensure_message_contains(3, "inside");
00492                 ensure_message_contains(4, "outside(moo)");
00493                 ensure_message_contains(5, "uber(bar,moo)");
00494                 ensure_message_count(6);
00495                 
00496                 metaLogger();
00497                 ensure_message_contains(6, "logging");
00498                 ensure_message_contains(7, "meta(baz)");
00499                 ensure_message_count(8);
00500         }
00501         
00502         template<> template<>
00503                 // special handling of llerrs calls
00504         void ErrorTestObject::test<8>()
00505         {
00506                 LLError::setPrintLocation(false);
00507                 std::string location = errorReturningLocation();
00508                 
00509                 ensure_message_contains(0, location + "error");
00510                 ensure_message_contains(1, "die");
00511                 ensure_message_count(2);
00512                 
00513                 ensure("fatal callback called", fatalWasCalled);
00514         }
00515 }
00516 
00517 namespace
00518 {
00519         std::string roswell()
00520         {
00521                 return "1947-07-08T03:04:05Z";
00522         }
00523         
00524         void ufoSighting()
00525         {
00526                 llinfos << "ufo" << llendl;
00527         }
00528 }
00529 
00530 namespace tut
00531 {       
00532         template<> template<>
00533                 // time in output (for recorders that need it)
00534         void ErrorTestObject::test<9>()
00535         {
00536                 LLError::setTimeFunction(roswell);
00537 
00538                 mRecorder.setWantsTime(false);
00539                 ufoSighting();
00540                 ensure_message_contains(0, "ufo");
00541                 ensure_message_does_not_contain(0, roswell());
00542                 
00543                 mRecorder.setWantsTime(true);
00544                 ufoSighting();
00545                 ensure_message_contains(1, "ufo");
00546                 ensure_message_contains(1, roswell());
00547         }
00548         
00549         template<> template<>
00550                 // output order
00551         void ErrorTestObject::test<10>()
00552         {
00553                 LLError::setPrintLocation(true);
00554                 LLError::setTimeFunction(roswell);
00555                 mRecorder.setWantsTime(true);
00556                 std::string locationAndFunction = writeReturningLocationAndFunction();
00557                 
00558                 ensure_equals("order is time type location function message",
00559                         mRecorder.message(0),
00560                         roswell() + " INFO: " + locationAndFunction + ": apple");
00561         }
00562 
00563         template<> template<>
00564                 // multiple recorders
00565         void ErrorTestObject::test<11>()
00566         {
00567                 TestRecorder altRecorder;
00568                 LLError::addRecorder(&altRecorder);
00569                 
00570                 llinfos << "boo" << llendl;
00571 
00572                 ensure_message_contains(0, "boo");
00573                 ensure_equals("alt recorder count", altRecorder.countMessages(), 1);
00574                 ensure_contains("alt recorder message 0", altRecorder.message(0), "boo");
00575                 
00576                 LLError::setTimeFunction(roswell);
00577 
00578                 TestRecorder anotherRecorder;
00579                 anotherRecorder.setWantsTime(true);
00580                 LLError::addRecorder(&anotherRecorder);
00581                 
00582                 llinfos << "baz" << llendl;
00583 
00584                 std::string when = roswell();
00585                 
00586                 ensure_message_does_not_contain(1, when);
00587                 ensure_equals("alt recorder count", altRecorder.countMessages(), 2);
00588                 ensure_does_not_contain("alt recorder message 1", altRecorder.message(1), when);
00589                 ensure_equals("another recorder count", anotherRecorder.countMessages(), 1);
00590                 ensure_contains("another recorder message 0", anotherRecorder.message(0), when);
00591         }
00592 }
00593 
00594 class TestAlpha
00595 {
00596         LOG_CLASS(TestAlpha);
00597 public:
00598         static void doDebug()   { lldebugs << "add dice" << llendl; }
00599         static void doInfo()    { llinfos  << "any idea" << llendl; }
00600         static void doWarn()    { llwarns  << "aim west" << llendl; }
00601         static void doError()   { llerrs   << "ate eels" << llendl; }
00602         static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
00603 };
00604 
00605 class TestBeta
00606 {
00607         LOG_CLASS(TestBeta);
00608 public:
00609         static void doDebug()   { lldebugs << "bed down" << llendl; }
00610         static void doInfo()    { llinfos  << "buy iron" << llendl; }
00611         static void doWarn()    { llwarns  << "bad word" << llendl; }
00612         static void doError()   { llerrs   << "big easy" << llendl; }
00613         static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
00614 };
00615 
00616 namespace tut
00617 {
00618         template<> template<>
00619                 // filtering by class
00620         void ErrorTestObject::test<12>()
00621         {
00622                 LLError::setDefaultLevel(LLError::LEVEL_WARN);
00623                 LLError::setClassLevel("TestBeta", LLError::LEVEL_INFO);
00624                 
00625                 TestAlpha::doAll();
00626                 TestBeta::doAll();
00627                 
00628                 ensure_message_contains(0, "aim west");
00629                 ensure_message_contains(1, "error");
00630                 ensure_message_contains(2, "ate eels");
00631                 ensure_message_contains(3, "buy iron");
00632                 ensure_message_contains(4, "bad word");
00633                 ensure_message_contains(5, "error");
00634                 ensure_message_contains(6, "big easy");
00635                 ensure_message_count(7);
00636         }
00637         
00638         template<> template<>
00639                 // filtering by function, and that it will override class filtering
00640         void ErrorTestObject::test<13>()
00641         {
00642                 LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
00643                 LLError::setClassLevel("TestBeta", LLError::LEVEL_WARN);
00644                 LLError::setFunctionLevel("TestBeta::doInfo", LLError::LEVEL_DEBUG);
00645                 LLError::setFunctionLevel("TestBeta::doError", LLError::LEVEL_NONE);
00646                 
00647                 TestBeta::doAll();
00648                 ensure_message_contains(0, "buy iron");
00649                 ensure_message_contains(1, "bad word");
00650                 ensure_message_count(2);
00651         }
00652         
00653         template<> template<>
00654                 // filtering by file
00655                 // and that it is overridden by both class and function filtering
00656         void ErrorTestObject::test<14>()
00657         {
00658                 LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
00659                 LLError::setFileLevel(LLError::abbreviateFile(__FILE__),
00660                                                                         LLError::LEVEL_WARN);
00661                 LLError::setClassLevel("TestAlpha", LLError::LEVEL_INFO);
00662                 LLError::setFunctionLevel("TestAlpha::doError",
00663                                                                         LLError::LEVEL_NONE);
00664                 LLError::setFunctionLevel("TestBeta::doError",
00665                                                                         LLError::LEVEL_NONE);
00666                 
00667                 TestAlpha::doAll();
00668                 TestBeta::doAll();
00669                 ensure_message_contains(0, "any idea");
00670                 ensure_message_contains(1, "aim west");
00671                 ensure_message_contains(2, "bad word");
00672                 ensure_message_count(3);
00673         }
00674         
00675         template<> template<>
00676                 // proper cached, efficient lookup of filtering
00677         void ErrorTestObject::test<15>()
00678         {
00679                 LLError::setDefaultLevel(LLError::LEVEL_NONE);
00680 
00681                 TestAlpha::doInfo();
00682                 ensure_message_count(0);
00683                 ensure_equals("first check", LLError::shouldLogCallCount(), 1);
00684                 TestAlpha::doInfo();
00685                 ensure_message_count(0);
00686                 ensure_equals("second check", LLError::shouldLogCallCount(), 1);
00687 
00688                 LLError::setClassLevel("TestAlpha", LLError::LEVEL_DEBUG);
00689                 TestAlpha::doInfo();
00690                 ensure_message_count(1);
00691                 ensure_equals("third check", LLError::shouldLogCallCount(), 2);
00692                 TestAlpha::doInfo();
00693                 ensure_message_count(2);
00694                 ensure_equals("fourth check", LLError::shouldLogCallCount(), 2);
00695 
00696                 LLError::setClassLevel("TestAlpha", LLError::LEVEL_WARN);
00697                 TestAlpha::doInfo();
00698                 ensure_message_count(2);
00699                 ensure_equals("fifth check", LLError::shouldLogCallCount(), 3);
00700                 TestAlpha::doInfo();
00701                 ensure_message_count(2);
00702                 ensure_equals("sixth check", LLError::shouldLogCallCount(), 3);
00703         }
00704         
00705         template<> template<>
00706                 // configuration from LLSD
00707         void ErrorTestObject::test<16>()
00708         {
00709                 std::string this_file = LLError::abbreviateFile(__FILE__);
00710                 LLSD config;
00711                 config["print-location"] = true;
00712                 config["default-level"] = "DEBUG";
00713                 
00714                 LLSD set1;
00715                 set1["level"] = "WARN";
00716                 set1["files"][0] = this_file;
00717                 
00718                 LLSD set2;
00719                 set2["level"] = "INFO";
00720                 set2["classes"][0] = "TestAlpha";
00721                 
00722                 LLSD set3;
00723                 set3["level"] = "NONE";
00724                 set3["functions"][0] = "TestAlpha::doError";
00725                 set3["functions"][1] = "TestBeta::doError";
00726                 
00727                 config["settings"][0] = set1;
00728                 config["settings"][1] = set2;
00729                 config["settings"][2] = set3;
00730                 
00731                 LLError::configure(config);
00732                 
00733                 TestAlpha::doAll();
00734                 TestBeta::doAll();
00735                 ensure_message_contains(0, "any idea");
00736                 ensure_message_contains(0, this_file);
00737                 ensure_message_contains(1, "aim west");
00738                 ensure_message_contains(2, "bad word");
00739                 ensure_message_count(3);
00740                 
00741                 // make sure reconfiguring works
00742                 LLSD config2;
00743                 config2["default-level"] = "WARN";
00744                 
00745                 LLError::configure(config2);
00746                 
00747                 TestAlpha::doAll();
00748                 TestBeta::doAll();
00749                 ensure_message_contains(3, "aim west");
00750                 ensure_message_does_not_contain(3, this_file);
00751                 ensure_message_contains(4, "error");
00752                 ensure_message_contains(5, "ate eels");
00753                 ensure_message_contains(6, "bad word");
00754                 ensure_message_contains(7, "error");
00755                 ensure_message_contains(8, "big easy");
00756                 ensure_message_count(9);
00757         }
00758 }       
00759 
00760 /* Tests left:
00761         handling of classes without LOG_CLASS
00762 
00763         live update of filtering from file      
00764         
00765         syslog recorder
00766         file recorder
00767         cerr/stderr recorder
00768         fixed buffer recorder
00769         windows recorder
00770 
00771         mutex use when logging (?)
00772         strange careful about to crash handling (?)
00773 */

Generated on Thu Jul 1 06:08:29 2010 for Second Life Viewer by  doxygen 1.4.7