2 var vows = require('vows')
3 , sandbox = require('sandboxed-module')
4 , assert = require('assert')
7 function makeFakeNet() {
12 createConnectionCalled: 0,
13 fakeAppender: function(logEvent) {
14 this.logEvents.push(logEvent);
16 createConnection: function(port, host) {
20 this.createConnectionCalled += 1;
22 on: function(evt, cb) {
23 fakeNet.cbs[evt] = cb;
25 write: function(data, encoding) {
26 fakeNet.data.push(data);
27 fakeNet.encoding = encoding;
30 fakeNet.closeCalled = true;
34 createServer: function(cb) {
37 remoteAddress: '1.2.3.4',
39 setEncoding: function(encoding) {
40 fakeNet.encoding = encoding;
42 on: function(event, cb) {
43 fakeNet.cbs[event] = cb;
48 listen: function(port, host) {
57 vows.describe('Multiprocess Appender').addBatch({
60 var fakeNet = makeFakeNet(),
61 appender = sandbox.require(
62 '../lib/appenders/multiprocess',
68 ).appender({ mode: 'worker', loggerPort: 1234, loggerHost: 'pants' });
70 //don't need a proper log event for the worker tests
71 appender('before connect');
72 fakeNet.cbs.connect();
73 appender('after connect');
74 fakeNet.cbs.close(true);
75 appender('after error, before connect');
76 fakeNet.cbs.connect();
77 appender('after error, after connect');
78 appender(new Error('Error test'));
82 'should open a socket to the loggerPort and loggerHost': function(net) {
83 assert.equal(net.port, 1234);
84 assert.equal(net.host, 'pants');
86 'should buffer messages written before socket is connected': function(net) {
87 assert.equal(net.data[0], JSON.stringify('before connect'));
89 'should write log messages to socket as json strings with a terminator string': function(net) {
90 assert.equal(net.data[0], JSON.stringify('before connect'));
91 assert.equal(net.data[1], '__LOG4JS__');
92 assert.equal(net.data[2], JSON.stringify('after connect'));
93 assert.equal(net.data[3], '__LOG4JS__');
94 assert.equal(net.encoding, 'utf8');
96 'should attempt to re-open the socket on error': function(net) {
97 assert.equal(net.data[4], JSON.stringify('after error, before connect'));
98 assert.equal(net.data[5], '__LOG4JS__');
99 assert.equal(net.data[6], JSON.stringify('after error, after connect'));
100 assert.equal(net.data[7], '__LOG4JS__');
101 assert.equal(net.createConnectionCalled, 2);
103 'should serialize an Error correctly': function(net) {
105 JSON.parse(net.data[8]).stack,
106 "Expected:\n\n" + net.data[8] + "\n\n to have a 'stack' property"
108 var actual = JSON.parse(net.data[8]).stack;
109 var expectedRegex = /^Error: Error test/;
111 actual.match(expectedRegex),
112 "Expected: \n\n " + actual + "\n\n to match " + expectedRegex
117 'worker with timeout': {
119 var fakeNet = makeFakeNet(),
120 appender = sandbox.require(
121 '../lib/appenders/multiprocess',
127 ).appender({ mode: 'worker' });
129 //don't need a proper log event for the worker tests
130 appender('before connect');
131 fakeNet.cbs.connect();
132 appender('after connect');
133 fakeNet.cbs.timeout();
134 appender('after timeout, before close');
136 appender('after close, before connect');
137 fakeNet.cbs.connect();
138 appender('after close, after connect');
142 'should attempt to re-open the socket': function(net) {
143 //skipping the __LOG4JS__ separators
144 assert.equal(net.data[0], JSON.stringify('before connect'));
145 assert.equal(net.data[2], JSON.stringify('after connect'));
146 assert.equal(net.data[4], JSON.stringify('after timeout, before close'));
147 assert.equal(net.data[6], JSON.stringify('after close, before connect'));
148 assert.equal(net.data[8], JSON.stringify('after close, after connect'));
149 assert.equal(net.createConnectionCalled, 2);
154 var fakeNet = makeFakeNet(),
155 appender = sandbox.require(
156 '../lib/appenders/multiprocess',
162 ).appender({ mode: 'worker' });
166 'should open a socket to localhost:5000': function(net) {
167 assert.equal(net.port, 5000);
168 assert.equal(net.host, 'localhost');
173 var fakeNet = makeFakeNet(),
174 appender = sandbox.require(
175 '../lib/appenders/multiprocess',
181 ).appender({ mode: 'master',
182 loggerHost: 'server',
184 actualAppender: fakeNet.fakeAppender.bind(fakeNet)
187 appender('this should be sent to the actual appender directly');
191 'should listen for log messages on loggerPort and loggerHost': function(net) {
192 assert.equal(net.port, 1234);
193 assert.equal(net.host, 'server');
195 'should return the underlying appender': function(net) {
196 assert.equal(net.logEvents[0], 'this should be sent to the actual appender directly');
198 'when a client connects': {
199 topic: function(net) {
200 var logString = JSON.stringify(
201 { level: { level: 10000, levelStr: 'DEBUG' }
202 , data: ['some debug']}
207 { level: { level: 40000, levelStr: 'ERROR' }
208 , data: ['an error message'] }
211 net.cbs.data(logString.substring(0, 10));
212 net.cbs.data(logString.substring(10));
213 net.cbs.data(logString + logString + logString);
216 { level: { level: 50000, levelStr: 'FATAL' }
217 , data: ["that's all folks"] }
220 net.cbs.data('bad message__LOG4JS__');
223 'should parse log messages into log events and send to appender': function(net) {
224 assert.equal(net.logEvents[1].level.toString(), 'ERROR');
225 assert.equal(net.logEvents[1].data[0], 'an error message');
226 assert.equal(net.logEvents[1].remoteAddress, '1.2.3.4');
227 assert.equal(net.logEvents[1].remotePort, '1234');
229 'should parse log messages split into multiple chunks': function(net) {
230 assert.equal(net.logEvents[2].level.toString(), 'DEBUG');
231 assert.equal(net.logEvents[2].data[0], 'some debug');
232 assert.equal(net.logEvents[2].remoteAddress, '1.2.3.4');
233 assert.equal(net.logEvents[2].remotePort, '1234');
235 'should parse multiple log messages in a single chunk': function(net) {
236 assert.equal(net.logEvents[3].data[0], 'some debug');
237 assert.equal(net.logEvents[4].data[0], 'some debug');
238 assert.equal(net.logEvents[5].data[0], 'some debug');
240 'should handle log messages sent as part of end event': function(net) {
241 assert.equal(net.logEvents[6].data[0], "that's all folks");
243 'should handle unparseable log messages': function(net) {
244 assert.equal(net.logEvents[7].level.toString(), 'ERROR');
245 assert.equal(net.logEvents[7].categoryName, 'log4js');
246 assert.equal(net.logEvents[7].data[0], 'Unable to parse log:');
247 assert.equal(net.logEvents[7].data[1], 'bad message');
253 var fakeNet = makeFakeNet(),
254 appender = sandbox.require(
255 '../lib/appenders/multiprocess',
261 ).appender({ mode: 'master' });
265 'should listen for log messages on localhost:5000': function(net) {
266 assert.equal(net.port, 5000);
267 assert.equal(net.host, 'localhost');
274 , fakeNet = makeFakeNet()
275 , appender = sandbox.require(
276 '../lib/appenders/multiprocess',
281 loadAppender: function(app) {
282 results.appenderLoaded = app;
285 'madeupappender': function(config, options) {
286 results.config = config;
287 results.options = options;
297 type: 'madeupappender',
301 { crackers: 'jacobs' }
307 'should load underlying appender for master': function(results) {
308 assert.equal(results.appenderLoaded, 'madeupappender');
310 'should pass config to underlying appender': function(results) {
311 assert.equal(results.config.cheese, 'gouda');
313 'should pass options to underlying appender': function(results) {
314 assert.equal(results.options.crackers, 'jacobs');