logging-test.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. "use strict";
  2. var vows = require('vows')
  3. , assert = require('assert')
  4. , sandbox = require('sandboxed-module');
  5. function setupConsoleTest() {
  6. var fakeConsole = {}
  7. , logEvents = []
  8. , log4js;
  9. ['trace','debug','log','info','warn','error'].forEach(function(fn) {
  10. fakeConsole[fn] = function() {
  11. throw new Error("this should not be called.");
  12. };
  13. });
  14. log4js = sandbox.require(
  15. '../lib/log4js',
  16. {
  17. globals: {
  18. console: fakeConsole
  19. }
  20. }
  21. );
  22. log4js.clearAppenders();
  23. log4js.addAppender(function(evt) {
  24. logEvents.push(evt);
  25. });
  26. return { log4js: log4js, logEvents: logEvents, fakeConsole: fakeConsole };
  27. }
  28. vows.describe('log4js').addBatch({
  29. 'getLogger': {
  30. topic: function() {
  31. var log4js = require('../lib/log4js');
  32. log4js.clearAppenders();
  33. var logger = log4js.getLogger('tests');
  34. logger.setLevel("DEBUG");
  35. return logger;
  36. },
  37. 'should take a category and return a logger': function(logger) {
  38. assert.equal(logger.category, 'tests');
  39. assert.equal(logger.level.toString(), "DEBUG");
  40. assert.isFunction(logger.debug);
  41. assert.isFunction(logger.info);
  42. assert.isFunction(logger.warn);
  43. assert.isFunction(logger.error);
  44. assert.isFunction(logger.fatal);
  45. },
  46. 'log events' : {
  47. topic: function(logger) {
  48. var events = [];
  49. logger.addListener("log", function (logEvent) { events.push(logEvent); });
  50. logger.debug("Debug event");
  51. logger.trace("Trace event 1");
  52. logger.trace("Trace event 2");
  53. logger.warn("Warning event");
  54. logger.error("Aargh!", new Error("Pants are on fire!"));
  55. logger.error("Simulated CouchDB problem", { err: 127, cause: "incendiary underwear" });
  56. return events;
  57. },
  58. 'should emit log events': function(events) {
  59. assert.equal(events[0].level.toString(), 'DEBUG');
  60. assert.equal(events[0].data[0], 'Debug event');
  61. assert.instanceOf(events[0].startTime, Date);
  62. },
  63. 'should not emit events of a lower level': function(events) {
  64. assert.equal(events.length, 4);
  65. assert.equal(events[1].level.toString(), 'WARN');
  66. },
  67. 'should include the error if passed in': function (events) {
  68. assert.instanceOf(events[2].data[1], Error);
  69. assert.equal(events[2].data[1].message, 'Pants are on fire!');
  70. }
  71. },
  72. },
  73. 'invalid configuration': {
  74. 'should throw an exception': function() {
  75. assert.throws(function() {
  76. require('log4js').configure({ "type": "invalid" });
  77. });
  78. }
  79. },
  80. 'configuration when passed as object': {
  81. topic: function() {
  82. var appenderConfig,
  83. log4js = sandbox.require(
  84. '../lib/log4js',
  85. {
  86. requires: {
  87. './appenders/file':
  88. {
  89. name: "file",
  90. appender: function() {},
  91. configure: function(configuration) {
  92. appenderConfig = configuration;
  93. return function() {};
  94. }
  95. }
  96. }
  97. }
  98. ),
  99. config = { appenders:
  100. [ { "type" : "file",
  101. "filename" : "cheesy-wotsits.log",
  102. "maxLogSize" : 1024,
  103. "backups" : 3
  104. }
  105. ]
  106. };
  107. log4js.configure(config);
  108. return appenderConfig;
  109. },
  110. 'should be passed to appender config': function(configuration) {
  111. assert.equal(configuration.filename, 'cheesy-wotsits.log');
  112. }
  113. },
  114. 'configuration that causes an error': {
  115. topic: function() {
  116. var log4js = sandbox.require(
  117. '../lib/log4js',
  118. {
  119. requires: {
  120. './appenders/file':
  121. {
  122. name: "file",
  123. appender: function() {},
  124. configure: function(configuration) {
  125. throw new Error("oh noes");
  126. }
  127. }
  128. }
  129. }
  130. ),
  131. config = { appenders:
  132. [ { "type" : "file",
  133. "filename" : "cheesy-wotsits.log",
  134. "maxLogSize" : 1024,
  135. "backups" : 3
  136. }
  137. ]
  138. };
  139. try {
  140. log4js.configure(config);
  141. } catch (e) {
  142. return e;
  143. }
  144. },
  145. 'should wrap error in a meaningful message': function(e) {
  146. assert.ok(e.message.indexOf('log4js configuration problem for') > -1);
  147. }
  148. },
  149. 'configuration when passed as filename': {
  150. topic: function() {
  151. var appenderConfig,
  152. configFilename,
  153. log4js = sandbox.require(
  154. '../lib/log4js',
  155. { requires:
  156. { 'fs':
  157. { statSync:
  158. function() {
  159. return { mtime: Date.now() };
  160. },
  161. readFileSync:
  162. function(filename) {
  163. configFilename = filename;
  164. return JSON.stringify({
  165. appenders: [
  166. { type: "file"
  167. , filename: "whatever.log"
  168. }
  169. ]
  170. });
  171. },
  172. readdirSync:
  173. function() {
  174. return ['file'];
  175. }
  176. },
  177. './appenders/file':
  178. { name: "file",
  179. appender: function() {},
  180. configure: function(configuration) {
  181. appenderConfig = configuration;
  182. return function() {};
  183. }
  184. }
  185. }
  186. }
  187. );
  188. log4js.configure("/path/to/cheese.json");
  189. return [ configFilename, appenderConfig ];
  190. },
  191. 'should read the config from a file': function(args) {
  192. assert.equal(args[0], '/path/to/cheese.json');
  193. },
  194. 'should pass config to appender': function(args) {
  195. assert.equal(args[1].filename, "whatever.log");
  196. }
  197. },
  198. 'with no appenders defined' : {
  199. topic: function() {
  200. var logger,
  201. that = this,
  202. fakeConsoleAppender = {
  203. name: "console",
  204. appender: function() {
  205. return function(evt) {
  206. that.callback(null, evt);
  207. };
  208. },
  209. configure: function() {
  210. return fakeConsoleAppender.appender();
  211. }
  212. },
  213. log4js = sandbox.require(
  214. '../lib/log4js',
  215. {
  216. requires: {
  217. './appenders/console': fakeConsoleAppender
  218. }
  219. }
  220. );
  221. logger = log4js.getLogger("some-logger");
  222. logger.debug("This is a test");
  223. },
  224. 'should default to the console appender': function(evt) {
  225. assert.equal(evt.data[0], "This is a test");
  226. }
  227. },
  228. 'addAppender' : {
  229. topic: function() {
  230. var log4js = require('../lib/log4js');
  231. log4js.clearAppenders();
  232. return log4js;
  233. },
  234. 'without a category': {
  235. 'should register the function as a listener for all loggers': function (log4js) {
  236. var appenderEvent,
  237. appender = function(evt) { appenderEvent = evt; },
  238. logger = log4js.getLogger("tests");
  239. log4js.addAppender(appender);
  240. logger.debug("This is a test");
  241. assert.equal(appenderEvent.data[0], "This is a test");
  242. assert.equal(appenderEvent.categoryName, "tests");
  243. assert.equal(appenderEvent.level.toString(), "DEBUG");
  244. },
  245. 'if an appender for a category is defined': {
  246. 'should register for that category': function (log4js) {
  247. var otherEvent,
  248. appenderEvent,
  249. cheeseLogger;
  250. log4js.addAppender(function (evt) { appenderEvent = evt; });
  251. log4js.addAppender(function (evt) { otherEvent = evt; }, 'cheese');
  252. cheeseLogger = log4js.getLogger('cheese');
  253. cheeseLogger.debug('This is a test');
  254. assert.deepEqual(appenderEvent, otherEvent);
  255. assert.equal(otherEvent.data[0], 'This is a test');
  256. assert.equal(otherEvent.categoryName, 'cheese');
  257. otherEvent = undefined;
  258. appenderEvent = undefined;
  259. log4js.getLogger('pants').debug("this should not be propagated to otherEvent");
  260. assert.isUndefined(otherEvent);
  261. assert.equal(appenderEvent.data[0], "this should not be propagated to otherEvent");
  262. }
  263. }
  264. },
  265. 'with a category': {
  266. 'should only register the function as a listener for that category': function(log4js) {
  267. var appenderEvent,
  268. appender = function(evt) { appenderEvent = evt; },
  269. logger = log4js.getLogger("tests");
  270. log4js.addAppender(appender, 'tests');
  271. logger.debug('this is a category test');
  272. assert.equal(appenderEvent.data[0], 'this is a category test');
  273. appenderEvent = undefined;
  274. log4js.getLogger('some other category').debug('Cheese');
  275. assert.isUndefined(appenderEvent);
  276. }
  277. },
  278. 'with multiple categories': {
  279. 'should register the function as a listener for all the categories': function(log4js) {
  280. var appenderEvent,
  281. appender = function(evt) { appenderEvent = evt; },
  282. logger = log4js.getLogger('tests');
  283. log4js.addAppender(appender, 'tests', 'biscuits');
  284. logger.debug('this is a test');
  285. assert.equal(appenderEvent.data[0], 'this is a test');
  286. appenderEvent = undefined;
  287. var otherLogger = log4js.getLogger('biscuits');
  288. otherLogger.debug("mmm... garibaldis");
  289. assert.equal(appenderEvent.data[0], "mmm... garibaldis");
  290. appenderEvent = undefined;
  291. log4js.getLogger("something else").debug("pants");
  292. assert.isUndefined(appenderEvent);
  293. },
  294. 'should register the function when the list of categories is an array': function(log4js) {
  295. var appenderEvent,
  296. appender = function(evt) { appenderEvent = evt; };
  297. log4js.addAppender(appender, ['tests', 'pants']);
  298. log4js.getLogger('tests').debug('this is a test');
  299. assert.equal(appenderEvent.data[0], 'this is a test');
  300. appenderEvent = undefined;
  301. log4js.getLogger('pants').debug("big pants");
  302. assert.equal(appenderEvent.data[0], "big pants");
  303. appenderEvent = undefined;
  304. log4js.getLogger("something else").debug("pants");
  305. assert.isUndefined(appenderEvent);
  306. }
  307. }
  308. },
  309. 'default setup': {
  310. topic: function() {
  311. var appenderEvents = [],
  312. fakeConsole = {
  313. 'name': 'console',
  314. 'appender': function () {
  315. return function(evt) {
  316. appenderEvents.push(evt);
  317. };
  318. },
  319. 'configure': function (config) {
  320. return fakeConsole.appender();
  321. }
  322. },
  323. globalConsole = {
  324. log: function() { }
  325. },
  326. log4js = sandbox.require(
  327. '../lib/log4js',
  328. {
  329. requires: {
  330. './appenders/console': fakeConsole
  331. },
  332. globals: {
  333. console: globalConsole
  334. }
  335. }
  336. ),
  337. logger = log4js.getLogger('a-test');
  338. logger.debug("this is a test");
  339. globalConsole.log("this should not be logged");
  340. return appenderEvents;
  341. },
  342. 'should configure a console appender': function(appenderEvents) {
  343. assert.equal(appenderEvents[0].data[0], 'this is a test');
  344. },
  345. 'should not replace console.log with log4js version': function(appenderEvents) {
  346. assert.equal(appenderEvents.length, 1);
  347. }
  348. },
  349. 'console' : {
  350. topic: setupConsoleTest,
  351. 'when replaceConsole called': {
  352. topic: function(test) {
  353. test.log4js.replaceConsole();
  354. test.fakeConsole.log("Some debug message someone put in a module");
  355. test.fakeConsole.debug("Some debug");
  356. test.fakeConsole.error("An error");
  357. test.fakeConsole.info("some info");
  358. test.fakeConsole.warn("a warning");
  359. test.fakeConsole.log("cheese (%s) and biscuits (%s)", "gouda", "garibaldis");
  360. test.fakeConsole.log({ lumpy: "tapioca" });
  361. test.fakeConsole.log("count %d", 123);
  362. test.fakeConsole.log("stringify %j", { lumpy: "tapioca" });
  363. return test.logEvents;
  364. },
  365. 'should replace console.log methods with log4js ones': function(logEvents) {
  366. assert.equal(logEvents.length, 9);
  367. assert.equal(logEvents[0].data[0], "Some debug message someone put in a module");
  368. assert.equal(logEvents[0].level.toString(), "INFO");
  369. assert.equal(logEvents[1].data[0], "Some debug");
  370. assert.equal(logEvents[1].level.toString(), "DEBUG");
  371. assert.equal(logEvents[2].data[0], "An error");
  372. assert.equal(logEvents[2].level.toString(), "ERROR");
  373. assert.equal(logEvents[3].data[0], "some info");
  374. assert.equal(logEvents[3].level.toString(), "INFO");
  375. assert.equal(logEvents[4].data[0], "a warning");
  376. assert.equal(logEvents[4].level.toString(), "WARN");
  377. assert.equal(logEvents[5].data[0], "cheese (%s) and biscuits (%s)");
  378. assert.equal(logEvents[5].data[1], "gouda");
  379. assert.equal(logEvents[5].data[2], "garibaldis");
  380. }
  381. },
  382. 'when turned off': {
  383. topic: function(test) {
  384. test.log4js.restoreConsole();
  385. try {
  386. test.fakeConsole.log("This should cause the error described in the setup");
  387. } catch (e) {
  388. return e;
  389. }
  390. },
  391. 'should call the original console methods': function (err) {
  392. assert.instanceOf(err, Error);
  393. assert.equal(err.message, "this should not be called.");
  394. }
  395. }
  396. },
  397. 'console configuration': {
  398. topic: setupConsoleTest,
  399. 'when disabled': {
  400. topic: function(test) {
  401. test.log4js.replaceConsole();
  402. test.log4js.configure({ replaceConsole: false });
  403. try {
  404. test.fakeConsole.log("This should cause the error described in the setup");
  405. } catch (e) {
  406. return e;
  407. }
  408. },
  409. 'should allow for turning off console replacement': function (err) {
  410. assert.instanceOf(err, Error);
  411. assert.equal(err.message, 'this should not be called.');
  412. }
  413. },
  414. 'when enabled': {
  415. topic: function(test) {
  416. test.log4js.restoreConsole();
  417. test.log4js.configure({ replaceConsole: true });
  418. //log4js.configure clears all appenders
  419. test.log4js.addAppender(function(evt) {
  420. test.logEvents.push(evt);
  421. });
  422. test.fakeConsole.debug("Some debug");
  423. return test.logEvents;
  424. },
  425. 'should allow for turning on console replacement': function (logEvents) {
  426. assert.equal(logEvents.length, 1);
  427. assert.equal(logEvents[0].level.toString(), "DEBUG");
  428. assert.equal(logEvents[0].data[0], "Some debug");
  429. }
  430. }
  431. },
  432. 'configuration persistence' : {
  433. topic: function() {
  434. var logEvent,
  435. firstLog4js = require('../lib/log4js'),
  436. secondLog4js;
  437. firstLog4js.clearAppenders();
  438. firstLog4js.addAppender(function(evt) { logEvent = evt; });
  439. secondLog4js = require('../lib/log4js');
  440. secondLog4js.getLogger().info("This should go to the appender defined in firstLog4js");
  441. return logEvent;
  442. },
  443. 'should maintain appenders between requires': function (logEvent) {
  444. assert.equal(logEvent.data[0], "This should go to the appender defined in firstLog4js");
  445. }
  446. },
  447. 'getDefaultLogger': {
  448. topic: function() {
  449. return require('../lib/log4js').getDefaultLogger();
  450. },
  451. 'should return a logger': function(logger) {
  452. assert.ok(logger.info);
  453. assert.ok(logger.debug);
  454. assert.ok(logger.error);
  455. }
  456. }
  457. }).export(module);