logging_test.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. // Licensed to the Software Freedom Conservancy (SFC) under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. The SFC licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing,
  12. // software distributed under the License is distributed on an
  13. // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. // KIND, either express or implied. See the License for the
  15. // specific language governing permissions and limitations
  16. // under the License.
  17. 'use strict';
  18. const assert = require('assert');
  19. const sinon = require('sinon');
  20. const logging = require('../../lib/logging');
  21. describe('logging', function() {
  22. let mgr, root, clock;
  23. beforeEach(function setUp() {
  24. mgr = new logging.LogManager;
  25. root = mgr.getLogger('');
  26. clock = sinon.useFakeTimers();
  27. });
  28. afterEach(function tearDown() {
  29. clock.restore();
  30. });
  31. describe('LogManager', function() {
  32. describe('getLogger()', function() {
  33. it('handles falsey input', function() {
  34. assert.strictEqual(root, mgr.getLogger());
  35. assert.strictEqual(root, mgr.getLogger(''));
  36. assert.strictEqual(root, mgr.getLogger(null));
  37. assert.strictEqual(root, mgr.getLogger(0));
  38. });
  39. it('creates parent loggers', function() {
  40. let logger = mgr.getLogger('foo.bar.baz');
  41. assert.strictEqual(logger.parent_, mgr.getLogger('foo.bar'));
  42. logger = logger.parent_;
  43. assert.strictEqual(logger.parent_, mgr.getLogger('foo'));
  44. logger = logger.parent_;
  45. assert.strictEqual(logger.parent_, mgr.getLogger(''));
  46. assert.strictEqual(logger.parent_.parent_, null);
  47. });
  48. });
  49. });
  50. describe('Logger', function() {
  51. describe('getEffectiveLevel()', function() {
  52. it('defaults to OFF', function() {
  53. assert.strictEqual(root.getLevel(), logging.Level.OFF);
  54. assert.strictEqual(root.getEffectiveLevel(), logging.Level.OFF);
  55. root.setLevel(null);
  56. assert.strictEqual(root.getLevel(), null);
  57. assert.strictEqual(root.getEffectiveLevel(), logging.Level.OFF);
  58. });
  59. it('uses own level if set', function() {
  60. let logger = mgr.getLogger('foo.bar.baz');
  61. assert.strictEqual(logger.getLevel(), null);
  62. assert.strictEqual(logger.getEffectiveLevel(), logging.Level.OFF);
  63. logger.setLevel(logging.Level.INFO);
  64. assert.strictEqual(logger.getLevel(), logging.Level.INFO);
  65. assert.strictEqual(logger.getEffectiveLevel(), logging.Level.INFO);
  66. });
  67. it('uses level from set on nearest parent', function() {
  68. let ancestor = mgr.getLogger('foo');
  69. ancestor.setLevel(logging.Level.SEVERE);
  70. let logger = mgr.getLogger('foo.bar.baz');
  71. assert.strictEqual(logger.getLevel(), null);
  72. assert.strictEqual(logger.getEffectiveLevel(), logging.Level.SEVERE);
  73. });
  74. });
  75. describe('isLoggable()', function() {
  76. it('compares level against logger\'s effective level', function() {
  77. const log1 = mgr.getLogger('foo');
  78. log1.setLevel(logging.Level.WARNING);
  79. const log2 = mgr.getLogger('foo.bar.baz');
  80. assert(!log2.isLoggable(logging.Level.FINEST));
  81. assert(!log2.isLoggable(logging.Level.INFO));
  82. assert(log2.isLoggable(logging.Level.WARNING));
  83. assert(log2.isLoggable(logging.Level.SEVERE));
  84. log2.setLevel(logging.Level.INFO);
  85. assert(!log2.isLoggable(logging.Level.FINEST));
  86. assert(log2.isLoggable(logging.Level.INFO));
  87. assert(log2.isLoggable(logging.Level.WARNING));
  88. assert(log2.isLoggable(logging.Level.SEVERE));
  89. log2.setLevel(logging.Level.ALL);
  90. assert(log2.isLoggable(logging.Level.FINEST));
  91. assert(log2.isLoggable(logging.Level.INFO));
  92. assert(log2.isLoggable(logging.Level.WARNING));
  93. assert(log2.isLoggable(logging.Level.SEVERE));
  94. });
  95. it('Level.OFF is never loggable', function() {
  96. function test(level) {
  97. root.setLevel(level);
  98. assert(!root.isLoggable(logging.Level.OFF),
  99. 'OFF should not be loggable at ' + level);
  100. }
  101. test(logging.Level.ALL);
  102. test(logging.Level.INFO);
  103. test(logging.Level.OFF);
  104. });
  105. });
  106. describe('log()', function() {
  107. it('does not invoke loggable if message is not loggable', function() {
  108. const log = mgr.getLogger('foo');
  109. log.setLevel(logging.Level.OFF);
  110. let callback = sinon.spy();
  111. log.addHandler(callback);
  112. root.addHandler(callback);
  113. assert(!callback.called);
  114. });
  115. it('invokes handlers for each parent logger', function() {
  116. const cb1 = sinon.spy();
  117. const cb2 = sinon.spy();
  118. const cb3 = sinon.spy();
  119. const cb4 = sinon.spy();
  120. const log1 = mgr.getLogger('foo');
  121. const log2 = mgr.getLogger('foo.bar');
  122. const log3 = mgr.getLogger('foo.bar.baz');
  123. const log4 = mgr.getLogger('foo.bar.baz.quot');
  124. log1.addHandler(cb1);
  125. log1.setLevel(logging.Level.INFO);
  126. log2.addHandler(cb2);
  127. log2.setLevel(logging.Level.WARNING);
  128. log3.addHandler(cb3);
  129. log3.setLevel(logging.Level.FINER);
  130. clock.tick(123456);
  131. log4.finest('this is the finest message');
  132. log4.finer('this is a finer message');
  133. log4.info('this is an info message');
  134. log4.warning('this is a warning message');
  135. log4.severe('this is a severe message');
  136. assert.equal(4, cb1.callCount);
  137. assert.equal(4, cb2.callCount);
  138. assert.equal(4, cb3.callCount);
  139. const entry1 = new logging.Entry(
  140. logging.Level.FINER,
  141. '[foo.bar.baz.quot] this is a finer message',
  142. 123456);
  143. const entry2 = new logging.Entry(
  144. logging.Level.INFO,
  145. '[foo.bar.baz.quot] this is an info message',
  146. 123456);
  147. const entry3 = new logging.Entry(
  148. logging.Level.WARNING,
  149. '[foo.bar.baz.quot] this is a warning message',
  150. 123456);
  151. const entry4 = new logging.Entry(
  152. logging.Level.SEVERE,
  153. '[foo.bar.baz.quot] this is a severe message',
  154. 123456);
  155. check(cb1.getCall(0).args[0], entry1);
  156. check(cb1.getCall(1).args[0], entry2);
  157. check(cb1.getCall(2).args[0], entry3);
  158. check(cb1.getCall(3).args[0], entry4);
  159. check(cb2.getCall(0).args[0], entry1);
  160. check(cb2.getCall(1).args[0], entry2);
  161. check(cb2.getCall(2).args[0], entry3);
  162. check(cb2.getCall(3).args[0], entry4);
  163. check(cb3.getCall(0).args[0], entry1);
  164. check(cb3.getCall(1).args[0], entry2);
  165. check(cb3.getCall(2).args[0], entry3);
  166. check(cb3.getCall(3).args[0], entry4);
  167. function check(entry, expected) {
  168. assert.equal(entry.level, expected.level, 'wrong level');
  169. assert.equal(entry.message, expected.message, 'wrong message');
  170. assert.equal(entry.timestamp, expected.timestamp, 'wrong time');
  171. }
  172. });
  173. it('does not invoke removed handler', function() {
  174. root.setLevel(logging.Level.INFO);
  175. const cb = sinon.spy();
  176. root.addHandler(cb);
  177. root.info('hi');
  178. assert.equal(1, cb.callCount);
  179. assert(root.removeHandler(cb));
  180. root.info('bye');
  181. assert.equal(1, cb.callCount);
  182. assert(!root.removeHandler(cb));
  183. });
  184. });
  185. });
  186. describe('getLevel()', function() {
  187. it('converts named levels', function() {
  188. assert.strictEqual(logging.Level.DEBUG, logging.getLevel('DEBUG'));
  189. assert.strictEqual(logging.Level.ALL, logging.getLevel('FAKE'));
  190. });
  191. it('converts numeric levels', function() {
  192. assert.strictEqual(
  193. logging.Level.DEBUG,
  194. logging.getLevel(logging.Level.DEBUG.value));
  195. });
  196. it('normalizes numeric levels', function() {
  197. assert.strictEqual(
  198. logging.Level.OFF,
  199. logging.getLevel(logging.Level.OFF.value * 2));
  200. let diff = logging.Level.SEVERE.value - logging.Level.WARNING.value;
  201. assert.strictEqual(
  202. logging.Level.WARNING,
  203. logging.getLevel(logging.Level.WARNING.value + (diff * .5)));
  204. assert.strictEqual(logging.Level.ALL, logging.getLevel(0));
  205. assert.strictEqual(logging.Level.ALL, logging.getLevel(-1));
  206. });
  207. });
  208. describe('Preferences', function() {
  209. it('can be converted to JSON', function() {
  210. let prefs = new logging.Preferences;
  211. assert.equal('{}', JSON.stringify(prefs));
  212. prefs.setLevel('foo', logging.Level.DEBUG);
  213. assert.equal('{"foo":"DEBUG"}', JSON.stringify(prefs));
  214. prefs.setLevel(logging.Type.BROWSER, logging.Level.FINE);
  215. assert.equal('{"foo":"DEBUG","browser":"FINE"}', JSON.stringify(prefs));
  216. });
  217. });
  218. });