llerror_test.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:20k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llerror_test.cpp
  3.  * @date   December 2006
  4.  * @brief error unit tests
  5.  *
  6.  * $LicenseInfo:firstyear=2006&license=viewergpl$
  7.  * 
  8.  * Copyright (c) 2006-2010, Linden Research, Inc.
  9.  * 
  10.  * Second Life Viewer Source Code
  11.  * The source code in this file ("Source Code") is provided by Linden Lab
  12.  * to you under the terms of the GNU General Public License, version 2.0
  13.  * ("GPL"), unless you have obtained a separate licensing agreement
  14.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  15.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17.  * 
  18.  * There are special exceptions to the terms and conditions of the GPL as
  19.  * it is applied to this Source Code. View the full text of the exception
  20.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  21.  * online at
  22.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23.  * 
  24.  * By copying, modifying or distributing this software, you acknowledge
  25.  * that you have read and understood your obligations described above,
  26.  * and agree to abide by those obligations.
  27.  * 
  28.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30.  * COMPLETENESS OR PERFORMANCE.
  31.  * $/LicenseInfo$
  32.  */
  33. #include <vector>
  34. #include "linden_common.h"
  35. #include "../llerror.h"
  36. #include "../llerrorcontrol.h"
  37. #include "../llsd.h"
  38. #include "../test/lltut.h"
  39. namespace
  40. {
  41. void test_that_error_h_includes_enough_things_to_compile_a_message()
  42. {
  43. llinfos << "!" << llendl;
  44. }
  45. }
  46. namespace
  47. {
  48. static bool fatalWasCalled;
  49. void fatalCall(const std::string&) { fatalWasCalled = true; }
  50. class TestRecorder : public LLError::Recorder
  51. {
  52. public:
  53. TestRecorder() : mWantsTime(false) { }
  54. ~TestRecorder() { LLError::removeRecorder(this); }
  55. void recordMessage(LLError::ELevel level,
  56. const std::string& message)
  57. {
  58. mMessages.push_back(message);
  59. }
  60. int countMessages() { return (int) mMessages.size(); }
  61. void clearMessages() { mMessages.clear(); }
  62. void setWantsTime(bool t) { mWantsTime = t; }
  63. bool wantsTime() { return mWantsTime; }
  64. std::string message(int n)
  65. {
  66. std::ostringstream test_name;
  67. test_name << "testing message " << n << ", not enough messages";
  68. tut::ensure(test_name.str(), n < countMessages());
  69. return mMessages[n];
  70. }
  71. private:
  72. typedef std::vector<std::string> MessageVector;
  73. MessageVector mMessages;
  74. bool mWantsTime;
  75. };
  76. }
  77. namespace tut
  78. {
  79. struct ErrorTestData
  80. {
  81. TestRecorder mRecorder;
  82. LLError::Settings* mPriorErrorSettings;
  83. ErrorTestData()
  84. {
  85. fatalWasCalled = false;
  86. mPriorErrorSettings = LLError::saveAndResetSettings();
  87. LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
  88. LLError::setFatalFunction(fatalCall);
  89. LLError::addRecorder(&mRecorder);
  90. }
  91. ~ErrorTestData()
  92. {
  93. LLError::removeRecorder(&mRecorder);
  94. LLError::restoreSettings(mPriorErrorSettings);
  95. }
  96. void ensure_message_count(int expectedCount)
  97. {
  98. ensure_equals("message count", mRecorder.countMessages(), expectedCount);
  99. }
  100. void ensure_message_contains(int n, const std::string& expectedText)
  101. {
  102. std::ostringstream test_name;
  103. test_name << "testing message " << n;
  104. ensure_contains(test_name.str(), mRecorder.message(n), expectedText);
  105. }
  106. void ensure_message_does_not_contain(int n, const std::string& expectedText)
  107. {
  108. std::ostringstream test_name;
  109. test_name << "testing message " << n;
  110. ensure_does_not_contain(test_name.str(), mRecorder.message(n), expectedText);
  111. }
  112. };
  113. typedef test_group<ErrorTestData> ErrorTestGroup;
  114. typedef ErrorTestGroup::object ErrorTestObject;
  115. ErrorTestGroup errorTestGroup("error");
  116. template<> template<>
  117. void ErrorTestObject::test<1>()
  118. // basic test of output
  119. {
  120. llinfos << "test" << llendl;
  121. llinfos << "bob" << llendl;
  122. ensure_message_contains(0, "test");
  123. ensure_message_contains(1, "bob");
  124. }
  125. }
  126. namespace
  127. {
  128. void writeSome()
  129. {
  130. lldebugs << "one" << llendl;
  131. llinfos << "two" << llendl;
  132. llwarns << "three" << llendl;
  133. llerrs << "four" << llendl;
  134. // fatal messages write out and addtional "error" message
  135. }
  136. };
  137. namespace tut
  138. {
  139. template<> template<>
  140. void ErrorTestObject::test<2>()
  141. // messages are filtered based on default level
  142. {
  143. LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
  144. writeSome();
  145. ensure_message_contains(0, "one");
  146. ensure_message_contains(1, "two");
  147. ensure_message_contains(2, "three");
  148. ensure_message_contains(3, "error");
  149. ensure_message_contains(4, "four");
  150. ensure_message_count(5);
  151. LLError::setDefaultLevel(LLError::LEVEL_INFO);
  152. writeSome();
  153. ensure_message_contains(5, "two");
  154. ensure_message_contains(6, "three");
  155. ensure_message_contains(7, "error");
  156. ensure_message_contains(8, "four");
  157. ensure_message_count(9);
  158. LLError::setDefaultLevel(LLError::LEVEL_WARN);
  159. writeSome();
  160. ensure_message_contains(9, "three");
  161. ensure_message_contains(10, "error");
  162. ensure_message_contains(11, "four");
  163. ensure_message_count(12);
  164. LLError::setDefaultLevel(LLError::LEVEL_ERROR);
  165. writeSome();
  166. ensure_message_contains(12, "error");
  167. ensure_message_contains(13, "four");
  168. ensure_message_count(14);
  169. LLError::setDefaultLevel(LLError::LEVEL_NONE);
  170. writeSome();
  171. ensure_message_count(14);
  172. }
  173. template<> template<>
  174. void ErrorTestObject::test<3>()
  175. // error type string in output
  176. {
  177. writeSome();
  178. ensure_message_contains(0, "DEBUG: ");
  179. ensure_message_contains(1, "INFO: ");
  180. ensure_message_contains(2, "WARNING: ");
  181. ensure_message_does_not_contain(3, "ERROR");
  182. ensure_message_contains(4, "ERROR: ");
  183. ensure_message_count(5);
  184. }
  185. template<> template<>
  186. void ErrorTestObject::test<4>()
  187. // file abbreviation
  188. {
  189. std::string thisFile = __FILE__;
  190. std::string abbreviateFile = LLError::abbreviateFile(thisFile);
  191. ensure_ends_with("file name abbreviation",
  192. abbreviateFile,
  193. "llcommon/tests/llerror_test.cpp"
  194. );
  195. ensure_does_not_contain("file name abbreviation",
  196. abbreviateFile, "indra");
  197. std::string someFile =
  198. #if LL_WINDOWS
  199. "C:/amy/bob/cam.cpp"
  200. #else
  201. "/amy/bob/cam.cpp"
  202. #endif
  203. ;
  204. std::string someAbbreviation = LLError::abbreviateFile(someFile);
  205. ensure_equals("non-indra file abbreviation",
  206. someAbbreviation, someFile);
  207. }
  208. }
  209. namespace
  210. {
  211. std::string locationString(int line)
  212. {
  213. std::ostringstream location;
  214. location << LLError::abbreviateFile(__FILE__)
  215.  << "(" << line << ") : ";
  216.  
  217. return location.str();
  218. }
  219. std::string writeReturningLocation()
  220. {
  221. llinfos << "apple" << llendl; int this_line = __LINE__;
  222. return locationString(this_line);
  223. }
  224. std::string writeReturningLocationAndFunction()
  225. {
  226. llinfos << "apple" << llendl; int this_line = __LINE__;
  227. return locationString(this_line) + __FUNCTION__;
  228. }
  229. std::string errorReturningLocation()
  230. {
  231. llerrs << "die" << llendl; int this_line = __LINE__;
  232. return locationString(this_line);
  233. }
  234. }
  235. namespace tut
  236. {
  237. template<> template<>
  238. void ErrorTestObject::test<5>()
  239. // file and line information in log messages
  240. {
  241. std::string location = writeReturningLocation();
  242. // expecting default to not print location information
  243. LLError::setPrintLocation(true);
  244. writeReturningLocation();
  245. LLError::setPrintLocation(false);
  246. writeReturningLocation();
  247. ensure_message_does_not_contain(0, location);
  248. ensure_message_contains(1, location);
  249. ensure_message_does_not_contain(2, location);
  250. }
  251. }
  252. /* The following helper functions and class members all log a simple message
  253. from some particular function scope.  Each function takes a bool argument
  254. that indicates if it should log its own name or not (in the manner that
  255. existing log messages often do.)  The functions all return their C++
  256. name so that test can be substantial mechanized.
  257.  */
  258.  
  259. std::string logFromGlobal(bool id)
  260. {
  261. llinfos << (id ? "logFromGlobal: " : "") << "hi" << llendl;
  262. return "logFromGlobal";
  263. }
  264. static std::string logFromStatic(bool id)
  265. {
  266. llinfos << (id ? "logFromStatic: " : "") << "hi" << llendl;
  267. return "logFromStatic";
  268. }
  269. namespace
  270. {
  271. std::string logFromAnon(bool id)
  272. {
  273. llinfos << (id ? "logFromAnon: " : "") << "hi" << llendl;
  274. return "logFromAnon";
  275. }
  276. }
  277. namespace Foo {
  278. std::string logFromNamespace(bool id)
  279. {
  280. llinfos << (id ? "Foo::logFromNamespace: " : "") << "hi" << llendl;
  281. //return "Foo::logFromNamespace";
  282. // there is no standard way to get the namespace name, hence
  283. // we won't be testing for it
  284. return "logFromNamespace";
  285. }
  286. }
  287. namespace
  288. {
  289. class ClassWithNoLogType {
  290. public:
  291. std::string logFromMember(bool id)
  292. {
  293. llinfos << (id ? "ClassWithNoLogType::logFromMember: " : "") << "hi" << llendl;
  294. return "ClassWithNoLogType::logFromMember";
  295. }
  296. static std::string logFromStatic(bool id)
  297. {
  298. llinfos << (id ? "ClassWithNoLogType::logFromStatic: " : "") << "hi" << llendl;
  299. return "ClassWithNoLogType::logFromStatic";
  300. }
  301. };
  302. class ClassWithLogType {
  303. LOG_CLASS(ClassWithLogType);
  304. public:
  305. std::string logFromMember(bool id)
  306. {
  307. llinfos << (id ? "ClassWithLogType::logFromMember: " : "") << "hi" << llendl;
  308. return "ClassWithLogType::logFromMember";
  309. }
  310. static std::string logFromStatic(bool id)
  311. {
  312. llinfos << (id ? "ClassWithLogType::logFromStatic: " : "") << "hi" << llendl;
  313. return "ClassWithLogType::logFromStatic";
  314. }
  315. };
  316. std::string logFromNamespace(bool id) { return Foo::logFromNamespace(id); }
  317. std::string logFromClassWithNoLogTypeMember(bool id) { ClassWithNoLogType c; return c.logFromMember(id); }
  318. std::string logFromClassWithNoLogTypeStatic(bool id) { return ClassWithNoLogType::logFromStatic(id); }
  319. std::string logFromClassWithLogTypeMember(bool id) { ClassWithLogType c; return c.logFromMember(id); }
  320. std::string logFromClassWithLogTypeStatic(bool id) { return ClassWithLogType::logFromStatic(id); }
  321. void ensure_has(const std::string& message,
  322. const std::string& actual, const std::string& expected)
  323. {
  324. std::string::size_type n1 = actual.find(expected);
  325. if (n1 == std::string::npos)
  326. {
  327. std::stringstream ss;
  328. ss << message << ": " << "expected to find a copy of " << expected
  329. << " in actual " << actual;
  330. throw tut::failure(ss.str().c_str());
  331. }
  332. }
  333. typedef std::string (*LogFromFunction)(bool);
  334. void testLogName(TestRecorder& recorder, LogFromFunction f,
  335. const std::string& class_name = "")
  336. {
  337. recorder.clearMessages();
  338. std::string name = f(false);
  339. f(true);
  340. std::string messageWithoutName = recorder.message(0);
  341. std::string messageWithName = recorder.message(1);
  342. ensure_has(name + " logged without name",
  343. messageWithoutName, name);
  344. ensure_has(name + " logged with name",
  345. messageWithName, name);
  346. if (!class_name.empty())
  347. {
  348. ensure_has(name + "logged without name",
  349. messageWithoutName, class_name);
  350. ensure_has(name + "logged with name",
  351. messageWithName, class_name);
  352. }
  353. }
  354. }
  355. namespace tut
  356. {
  357. template<> template<>
  358. //  class/function information in output
  359. void ErrorTestObject::test<6>()
  360. {
  361. testLogName(mRecorder, logFromGlobal);
  362. testLogName(mRecorder, logFromStatic);
  363. testLogName(mRecorder, logFromAnon);
  364. testLogName(mRecorder, logFromNamespace);
  365. //testLogName(mRecorder, logFromClassWithNoLogTypeMember, "ClassWithNoLogType");
  366. //testLogName(mRecorder, logFromClassWithNoLogTypeStatic, "ClassWithNoLogType");
  367. // XXX: figure out what the exepcted response is for these
  368. testLogName(mRecorder, logFromClassWithLogTypeMember, "ClassWithLogType");
  369. testLogName(mRecorder, logFromClassWithLogTypeStatic, "ClassWithLogType");
  370. }
  371. }
  372. namespace
  373. {
  374. std::string innerLogger()
  375. {
  376. llinfos << "inside" << llendl;
  377. return "moo";
  378. }
  379. std::string outerLogger()
  380. {
  381. llinfos << "outside(" << innerLogger() << ")" << llendl;
  382. return "bar";
  383. }
  384. void uberLogger()
  385. {
  386. llinfos << "uber(" << outerLogger() << "," << innerLogger() << ")" << llendl;
  387. }
  388. class LogWhileLogging
  389. {
  390. public:
  391. void print(std::ostream& out) const
  392. {
  393. llinfos << "logging" << llendl;
  394. out << "baz";
  395. }
  396. };
  397. std::ostream& operator<<(std::ostream& out, const LogWhileLogging& l)
  398. { l.print(out); return out; }
  399. void metaLogger()
  400. {
  401. LogWhileLogging l;
  402. llinfos << "meta(" << l << ")" << llendl;
  403. }
  404. }
  405. namespace tut
  406. {
  407. template<> template<>
  408. // handle nested logging
  409. void ErrorTestObject::test<7>()
  410. {
  411. outerLogger();
  412. ensure_message_contains(0, "inside");
  413. ensure_message_contains(1, "outside(moo)");
  414. ensure_message_count(2);
  415. uberLogger();
  416. ensure_message_contains(2, "inside");
  417. ensure_message_contains(3, "inside");
  418. ensure_message_contains(4, "outside(moo)");
  419. ensure_message_contains(5, "uber(bar,moo)");
  420. ensure_message_count(6);
  421. metaLogger();
  422. ensure_message_contains(6, "logging");
  423. ensure_message_contains(7, "meta(baz)");
  424. ensure_message_count(8);
  425. }
  426. template<> template<>
  427. // special handling of llerrs calls
  428. void ErrorTestObject::test<8>()
  429. {
  430. LLError::setPrintLocation(false);
  431. std::string location = errorReturningLocation();
  432. ensure_message_contains(0, location + "error");
  433. ensure_message_contains(1, "die");
  434. ensure_message_count(2);
  435. ensure("fatal callback called", fatalWasCalled);
  436. }
  437. }
  438. namespace
  439. {
  440. std::string roswell()
  441. {
  442. return "1947-07-08T03:04:05Z";
  443. }
  444. void ufoSighting()
  445. {
  446. llinfos << "ufo" << llendl;
  447. }
  448. }
  449. namespace tut
  450. {
  451. template<> template<>
  452. // time in output (for recorders that need it)
  453. void ErrorTestObject::test<9>()
  454. {
  455. LLError::setTimeFunction(roswell);
  456. mRecorder.setWantsTime(false);
  457. ufoSighting();
  458. ensure_message_contains(0, "ufo");
  459. ensure_message_does_not_contain(0, roswell());
  460. mRecorder.setWantsTime(true);
  461. ufoSighting();
  462. ensure_message_contains(1, "ufo");
  463. ensure_message_contains(1, roswell());
  464. }
  465. template<> template<>
  466. // output order
  467. void ErrorTestObject::test<10>()
  468. {
  469. #if LL_LINUX
  470.         skip("Fails on Linux, see comments");
  471. // on Linux:
  472. // [error, 10] fail: 'order is time type location function message: expected
  473. // '1947-07-08T03:04:05Z INFO: llcommon/tests/llerror_test.cpp(268) :
  474. // writeReturningLocationAndFunction: apple' actual
  475. // '1947-07-08T03:04:05Z INFO: llcommon/tests/llerror_test.cpp(268) :
  476. // LLError::NoClassInfo::writeReturningLocationAndFunction: apple''
  477. #endif
  478. LLError::setPrintLocation(true);
  479. LLError::setTimeFunction(roswell);
  480. mRecorder.setWantsTime(true);
  481. std::string locationAndFunction = writeReturningLocationAndFunction();
  482. ensure_equals("order is time type location function message",
  483. mRecorder.message(0),
  484. roswell() + " INFO: " + locationAndFunction + ": apple");
  485. }
  486. template<> template<>
  487. // multiple recorders
  488. void ErrorTestObject::test<11>()
  489. {
  490. TestRecorder altRecorder;
  491. LLError::addRecorder(&altRecorder);
  492. llinfos << "boo" << llendl;
  493. ensure_message_contains(0, "boo");
  494. ensure_equals("alt recorder count", altRecorder.countMessages(), 1);
  495. ensure_contains("alt recorder message 0", altRecorder.message(0), "boo");
  496. LLError::setTimeFunction(roswell);
  497. TestRecorder anotherRecorder;
  498. anotherRecorder.setWantsTime(true);
  499. LLError::addRecorder(&anotherRecorder);
  500. llinfos << "baz" << llendl;
  501. std::string when = roswell();
  502. ensure_message_does_not_contain(1, when);
  503. ensure_equals("alt recorder count", altRecorder.countMessages(), 2);
  504. ensure_does_not_contain("alt recorder message 1", altRecorder.message(1), when);
  505. ensure_equals("another recorder count", anotherRecorder.countMessages(), 1);
  506. ensure_contains("another recorder message 0", anotherRecorder.message(0), when);
  507. }
  508. }
  509. class TestAlpha
  510. {
  511. LOG_CLASS(TestAlpha);
  512. public:
  513. static void doDebug() { lldebugs << "add dice" << llendl; }
  514. static void doInfo() { llinfos  << "any idea" << llendl; }
  515. static void doWarn() { llwarns  << "aim west" << llendl; }
  516. static void doError() { llerrs   << "ate eels" << llendl; }
  517. static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
  518. };
  519. class TestBeta
  520. {
  521. LOG_CLASS(TestBeta);
  522. public:
  523. static void doDebug() { lldebugs << "bed down" << llendl; }
  524. static void doInfo() { llinfos  << "buy iron" << llendl; }
  525. static void doWarn() { llwarns  << "bad word" << llendl; }
  526. static void doError() { llerrs   << "big easy" << llendl; }
  527. static void doAll() { doDebug(); doInfo(); doWarn(); doError(); }
  528. };
  529. namespace tut
  530. {
  531. template<> template<>
  532. // filtering by class
  533. void ErrorTestObject::test<12>()
  534. {
  535. LLError::setDefaultLevel(LLError::LEVEL_WARN);
  536. LLError::setClassLevel("TestBeta", LLError::LEVEL_INFO);
  537. TestAlpha::doAll();
  538. TestBeta::doAll();
  539. ensure_message_contains(0, "aim west");
  540. ensure_message_contains(1, "error");
  541. ensure_message_contains(2, "ate eels");
  542. ensure_message_contains(3, "buy iron");
  543. ensure_message_contains(4, "bad word");
  544. ensure_message_contains(5, "error");
  545. ensure_message_contains(6, "big easy");
  546. ensure_message_count(7);
  547. }
  548. template<> template<>
  549. // filtering by function, and that it will override class filtering
  550. void ErrorTestObject::test<13>()
  551. {
  552. LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
  553. LLError::setClassLevel("TestBeta", LLError::LEVEL_WARN);
  554. LLError::setFunctionLevel("TestBeta::doInfo", LLError::LEVEL_DEBUG);
  555. LLError::setFunctionLevel("TestBeta::doError", LLError::LEVEL_NONE);
  556. TestBeta::doAll();
  557. ensure_message_contains(0, "buy iron");
  558. ensure_message_contains(1, "bad word");
  559. ensure_message_count(2);
  560. }
  561. template<> template<>
  562. // filtering by file
  563. // and that it is overridden by both class and function filtering
  564. void ErrorTestObject::test<14>()
  565. {
  566. LLError::setDefaultLevel(LLError::LEVEL_DEBUG);
  567. LLError::setFileLevel(LLError::abbreviateFile(__FILE__),
  568. LLError::LEVEL_WARN);
  569. LLError::setClassLevel("TestAlpha", LLError::LEVEL_INFO);
  570. LLError::setFunctionLevel("TestAlpha::doError",
  571. LLError::LEVEL_NONE);
  572. LLError::setFunctionLevel("TestBeta::doError",
  573. LLError::LEVEL_NONE);
  574. TestAlpha::doAll();
  575. TestBeta::doAll();
  576. ensure_message_contains(0, "any idea");
  577. ensure_message_contains(1, "aim west");
  578. ensure_message_contains(2, "bad word");
  579. ensure_message_count(3);
  580. }
  581. template<> template<>
  582. // proper cached, efficient lookup of filtering
  583. void ErrorTestObject::test<15>()
  584. {
  585. LLError::setDefaultLevel(LLError::LEVEL_NONE);
  586. TestAlpha::doInfo();
  587. ensure_message_count(0);
  588. ensure_equals("first check", LLError::shouldLogCallCount(), 1);
  589. TestAlpha::doInfo();
  590. ensure_message_count(0);
  591. ensure_equals("second check", LLError::shouldLogCallCount(), 1);
  592. LLError::setClassLevel("TestAlpha", LLError::LEVEL_DEBUG);
  593. TestAlpha::doInfo();
  594. ensure_message_count(1);
  595. ensure_equals("third check", LLError::shouldLogCallCount(), 2);
  596. TestAlpha::doInfo();
  597. ensure_message_count(2);
  598. ensure_equals("fourth check", LLError::shouldLogCallCount(), 2);
  599. LLError::setClassLevel("TestAlpha", LLError::LEVEL_WARN);
  600. TestAlpha::doInfo();
  601. ensure_message_count(2);
  602. ensure_equals("fifth check", LLError::shouldLogCallCount(), 3);
  603. TestAlpha::doInfo();
  604. ensure_message_count(2);
  605. ensure_equals("sixth check", LLError::shouldLogCallCount(), 3);
  606. }
  607. template<> template<>
  608. // configuration from LLSD
  609. void ErrorTestObject::test<16>()
  610. {
  611. std::string this_file = LLError::abbreviateFile(__FILE__);
  612. LLSD config;
  613. config["print-location"] = true;
  614. config["default-level"] = "DEBUG";
  615. LLSD set1;
  616. set1["level"] = "WARN";
  617. set1["files"][0] = this_file;
  618. LLSD set2;
  619. set2["level"] = "INFO";
  620. set2["classes"][0] = "TestAlpha";
  621. LLSD set3;
  622. set3["level"] = "NONE";
  623. set3["functions"][0] = "TestAlpha::doError";
  624. set3["functions"][1] = "TestBeta::doError";
  625. config["settings"][0] = set1;
  626. config["settings"][1] = set2;
  627. config["settings"][2] = set3;
  628. LLError::configure(config);
  629. TestAlpha::doAll();
  630. TestBeta::doAll();
  631. ensure_message_contains(0, "any idea");
  632. ensure_message_contains(0, this_file);
  633. ensure_message_contains(1, "aim west");
  634. ensure_message_contains(2, "bad word");
  635. ensure_message_count(3);
  636. // make sure reconfiguring works
  637. LLSD config2;
  638. config2["default-level"] = "WARN";
  639. LLError::configure(config2);
  640. TestAlpha::doAll();
  641. TestBeta::doAll();
  642. ensure_message_contains(3, "aim west");
  643. ensure_message_does_not_contain(3, this_file);
  644. ensure_message_contains(4, "error");
  645. ensure_message_contains(5, "ate eels");
  646. ensure_message_contains(6, "bad word");
  647. ensure_message_contains(7, "error");
  648. ensure_message_contains(8, "big easy");
  649. ensure_message_count(9);
  650. }
  651. }
  652. /* Tests left:
  653. handling of classes without LOG_CLASS
  654. live update of filtering from file
  655. syslog recorder
  656. file recorder
  657. cerr/stderr recorder
  658. fixed buffer recorder
  659. windows recorder
  660. mutex use when logging (?)
  661. strange careful about to crash handling (?)
  662. */