multiprocess-test.js 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. "use strict";
  2. var vows = require('vows')
  3. , sandbox = require('sandboxed-module')
  4. , assert = require('assert')
  5. ;
  6. function makeFakeNet() {
  7. return {
  8. logEvents: [],
  9. data: [],
  10. cbs: {},
  11. createConnectionCalled: 0,
  12. fakeAppender: function(logEvent) {
  13. this.logEvents.push(logEvent);
  14. },
  15. createConnection: function(port, host) {
  16. var fakeNet = this;
  17. this.port = port;
  18. this.host = host;
  19. this.createConnectionCalled += 1;
  20. return {
  21. on: function(evt, cb) {
  22. fakeNet.cbs[evt] = cb;
  23. },
  24. write: function(data, encoding) {
  25. fakeNet.data.push(data);
  26. fakeNet.encoding = encoding;
  27. },
  28. end: function() {
  29. fakeNet.closeCalled = true;
  30. }
  31. };
  32. },
  33. createServer: function(cb) {
  34. var fakeNet = this;
  35. cb({
  36. remoteAddress: '1.2.3.4',
  37. remotePort: '1234',
  38. setEncoding: function(encoding) {
  39. fakeNet.encoding = encoding;
  40. },
  41. on: function(event, cb) {
  42. fakeNet.cbs[event] = cb;
  43. }
  44. });
  45. return {
  46. listen: function(port, host) {
  47. fakeNet.port = port;
  48. fakeNet.host = host;
  49. }
  50. };
  51. }
  52. };
  53. }
  54. vows.describe('Multiprocess Appender').addBatch({
  55. 'worker': {
  56. topic: function() {
  57. var fakeNet = makeFakeNet(),
  58. appender = sandbox.require(
  59. '../lib/appenders/multiprocess',
  60. {
  61. requires: {
  62. 'net': fakeNet
  63. }
  64. }
  65. ).appender({ mode: 'worker', loggerPort: 1234, loggerHost: 'pants' });
  66. //don't need a proper log event for the worker tests
  67. appender('before connect');
  68. fakeNet.cbs.connect();
  69. appender('after connect');
  70. fakeNet.cbs.close(true);
  71. appender('after error, before connect');
  72. fakeNet.cbs.connect();
  73. appender('after error, after connect');
  74. return fakeNet;
  75. },
  76. 'should open a socket to the loggerPort and loggerHost': function(net) {
  77. assert.equal(net.port, 1234);
  78. assert.equal(net.host, 'pants');
  79. },
  80. 'should buffer messages written before socket is connected': function(net) {
  81. assert.equal(net.data[0], JSON.stringify('before connect'));
  82. },
  83. 'should write log messages to socket as json strings with a terminator string': function(net) {
  84. assert.equal(net.data[0], JSON.stringify('before connect'));
  85. assert.equal(net.data[1], '__LOG4JS__');
  86. assert.equal(net.data[2], JSON.stringify('after connect'));
  87. assert.equal(net.data[3], '__LOG4JS__');
  88. assert.equal(net.encoding, 'utf8');
  89. },
  90. 'should attempt to re-open the socket on error': function(net) {
  91. assert.equal(net.data[4], JSON.stringify('after error, before connect'));
  92. assert.equal(net.data[5], '__LOG4JS__');
  93. assert.equal(net.data[6], JSON.stringify('after error, after connect'));
  94. assert.equal(net.data[7], '__LOG4JS__');
  95. assert.equal(net.createConnectionCalled, 2);
  96. }
  97. },
  98. 'worker with timeout': {
  99. topic: function() {
  100. var fakeNet = makeFakeNet(),
  101. appender = sandbox.require(
  102. '../lib/appenders/multiprocess',
  103. {
  104. requires: {
  105. 'net': fakeNet
  106. }
  107. }
  108. ).appender({ mode: 'worker' });
  109. //don't need a proper log event for the worker tests
  110. appender('before connect');
  111. fakeNet.cbs.connect();
  112. appender('after connect');
  113. fakeNet.cbs.timeout();
  114. appender('after timeout, before close');
  115. fakeNet.cbs.close();
  116. appender('after close, before connect');
  117. fakeNet.cbs.connect();
  118. appender('after close, after connect');
  119. return fakeNet;
  120. },
  121. 'should attempt to re-open the socket': function(net) {
  122. //skipping the __LOG4JS__ separators
  123. assert.equal(net.data[0], JSON.stringify('before connect'));
  124. assert.equal(net.data[2], JSON.stringify('after connect'));
  125. assert.equal(net.data[4], JSON.stringify('after timeout, before close'));
  126. assert.equal(net.data[6], JSON.stringify('after close, before connect'));
  127. assert.equal(net.data[8], JSON.stringify('after close, after connect'));
  128. assert.equal(net.createConnectionCalled, 2);
  129. }
  130. },
  131. 'worker defaults': {
  132. topic: function() {
  133. var fakeNet = makeFakeNet(),
  134. appender = sandbox.require(
  135. '../lib/appenders/multiprocess',
  136. {
  137. requires: {
  138. 'net': fakeNet
  139. }
  140. }
  141. ).appender({ mode: 'worker' });
  142. return fakeNet;
  143. },
  144. 'should open a socket to localhost:5000': function(net) {
  145. assert.equal(net.port, 5000);
  146. assert.equal(net.host, 'localhost');
  147. }
  148. },
  149. 'master': {
  150. topic: function() {
  151. var fakeNet = makeFakeNet(),
  152. appender = sandbox.require(
  153. '../lib/appenders/multiprocess',
  154. {
  155. requires: {
  156. 'net': fakeNet
  157. }
  158. }
  159. ).appender({ mode: 'master',
  160. loggerHost: 'server',
  161. loggerPort: 1234,
  162. actualAppender: fakeNet.fakeAppender.bind(fakeNet)
  163. });
  164. appender('this should be sent to the actual appender directly');
  165. return fakeNet;
  166. },
  167. 'should listen for log messages on loggerPort and loggerHost': function(net) {
  168. assert.equal(net.port, 1234);
  169. assert.equal(net.host, 'server');
  170. },
  171. 'should return the underlying appender': function(net) {
  172. assert.equal(net.logEvents[0], 'this should be sent to the actual appender directly');
  173. },
  174. 'when a client connects': {
  175. topic: function(net) {
  176. var logString = JSON.stringify(
  177. { level: { level: 10000, levelStr: 'DEBUG' }
  178. , data: ['some debug']}
  179. ) + '__LOG4JS__';
  180. net.cbs.data(
  181. JSON.stringify(
  182. { level: { level: 40000, levelStr: 'ERROR' }
  183. , data: ['an error message'] }
  184. ) + '__LOG4JS__'
  185. );
  186. net.cbs.data(logString.substring(0, 10));
  187. net.cbs.data(logString.substring(10));
  188. net.cbs.data(logString + logString + logString);
  189. net.cbs.end(
  190. JSON.stringify(
  191. { level: { level: 50000, levelStr: 'FATAL' }
  192. , data: ["that's all folks"] }
  193. ) + '__LOG4JS__'
  194. );
  195. net.cbs.data('bad message__LOG4JS__');
  196. return net;
  197. },
  198. 'should parse log messages into log events and send to appender': function(net) {
  199. assert.equal(net.logEvents[1].level.toString(), 'ERROR');
  200. assert.equal(net.logEvents[1].data[0], 'an error message');
  201. assert.equal(net.logEvents[1].remoteAddress, '1.2.3.4');
  202. assert.equal(net.logEvents[1].remotePort, '1234');
  203. },
  204. 'should parse log messages split into multiple chunks': function(net) {
  205. assert.equal(net.logEvents[2].level.toString(), 'DEBUG');
  206. assert.equal(net.logEvents[2].data[0], 'some debug');
  207. assert.equal(net.logEvents[2].remoteAddress, '1.2.3.4');
  208. assert.equal(net.logEvents[2].remotePort, '1234');
  209. },
  210. 'should parse multiple log messages in a single chunk': function(net) {
  211. assert.equal(net.logEvents[3].data[0], 'some debug');
  212. assert.equal(net.logEvents[4].data[0], 'some debug');
  213. assert.equal(net.logEvents[5].data[0], 'some debug');
  214. },
  215. 'should handle log messages sent as part of end event': function(net) {
  216. assert.equal(net.logEvents[6].data[0], "that's all folks");
  217. },
  218. 'should handle unparseable log messages': function(net) {
  219. assert.equal(net.logEvents[7].level.toString(), 'ERROR');
  220. assert.equal(net.logEvents[7].categoryName, 'log4js');
  221. assert.equal(net.logEvents[7].data[0], 'Unable to parse log:');
  222. assert.equal(net.logEvents[7].data[1], 'bad message');
  223. }
  224. }
  225. },
  226. 'master defaults': {
  227. topic: function() {
  228. var fakeNet = makeFakeNet(),
  229. appender = sandbox.require(
  230. '../lib/appenders/multiprocess',
  231. {
  232. requires: {
  233. 'net': fakeNet
  234. }
  235. }
  236. ).appender({ mode: 'master' });
  237. return fakeNet;
  238. },
  239. 'should listen for log messages on localhost:5000': function(net) {
  240. assert.equal(net.port, 5000);
  241. assert.equal(net.host, 'localhost');
  242. }
  243. }
  244. }).addBatch({
  245. 'configure': {
  246. topic: function() {
  247. var results = {}
  248. , fakeNet = makeFakeNet()
  249. , appender = sandbox.require(
  250. '../lib/appenders/multiprocess',
  251. {
  252. requires: {
  253. 'net': fakeNet,
  254. '../log4js': {
  255. loadAppender: function(app) {
  256. results.appenderLoaded = app;
  257. },
  258. appenderMakers: {
  259. 'madeupappender': function(config, options) {
  260. results.config = config;
  261. results.options = options;
  262. }
  263. }
  264. }
  265. }
  266. }
  267. ).configure(
  268. {
  269. mode: 'master',
  270. appender: {
  271. type: 'madeupappender',
  272. cheese: 'gouda'
  273. }
  274. },
  275. { crackers: 'jacobs' }
  276. );
  277. return results;
  278. },
  279. 'should load underlying appender for master': function(results) {
  280. assert.equal(results.appenderLoaded, 'madeupappender');
  281. },
  282. 'should pass config to underlying appender': function(results) {
  283. assert.equal(results.config.cheese, 'gouda');
  284. },
  285. 'should pass options to underlying appender': function(results) {
  286. assert.equal(results.options.crackers, 'jacobs');
  287. }
  288. }
  289. }).exportTo(module);