many tests
This commit is contained in:
@ -57,6 +57,6 @@
|
||||
},
|
||||
"testling": {
|
||||
"harness": "mocha",
|
||||
"files": "test/unit/test_!(http_connector|stdio_logger).js"
|
||||
"files": "test/unit/test_!(http_connector|stdio_logger|stream_logger|tracer_logger|file_logger).js"
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,28 +5,53 @@ var path = require('path');
|
||||
var argv = require('optimist')
|
||||
.usage([
|
||||
'Runner for the Elasticsearch.js unit and integration tests in both node and the browser.',
|
||||
'Specify --no-{{flag}} to negate it.'
|
||||
'To negate a flag you can use --no-{{flag}}.',
|
||||
'',
|
||||
'Examples:',
|
||||
'',
|
||||
'# Before a commit (unit tests in Node & Phantom + integration in Chrome & Firefox):',
|
||||
'npm test --unit --integration --browsers=chrome,firefox',
|
||||
'',
|
||||
'# After a change in the rest-spec:',
|
||||
'npm test --no-unit --integration --browsers=chrome,firefox --check-upstream',
|
||||
'',
|
||||
'# During dev (just Node unit tests):',
|
||||
'npm test --no-browsers',
|
||||
''
|
||||
].join('\n'))
|
||||
.default({
|
||||
server: true,
|
||||
unit: true,
|
||||
integration: false,
|
||||
host: 'localhost',
|
||||
port: 9200,
|
||||
'xml-output': true,
|
||||
'check-upstream': false,
|
||||
'browsers': '*'
|
||||
})
|
||||
.describe({
|
||||
host: 'hostname for elasticsearch instance used in integration tests',
|
||||
'check-upstream': 'check for remote updates to the yaml test suite'
|
||||
})
|
||||
.alias({
|
||||
u: 'unit',
|
||||
i: 'integration',
|
||||
b: 'browsers',
|
||||
s: 'server',
|
||||
x: 'xml-output'
|
||||
.options({
|
||||
server: {
|
||||
default: true,
|
||||
alias: 's'
|
||||
},
|
||||
unit: {
|
||||
default: true,
|
||||
alias: 'u'
|
||||
},
|
||||
integration: {
|
||||
default: false,
|
||||
alias: 'i'
|
||||
},
|
||||
host: {
|
||||
default: 'localhost',
|
||||
description: 'hostname for elasticsearch instance used in integration tests'
|
||||
},
|
||||
port: {
|
||||
default: 9200,
|
||||
alias: 'p'
|
||||
},
|
||||
browsers: {
|
||||
default: '*',
|
||||
alias: 'b'
|
||||
},
|
||||
'xml-output': {
|
||||
default: true,
|
||||
alias: 'x'
|
||||
},
|
||||
'check-upstream': {
|
||||
default: false,
|
||||
description: 'check for remote updates to the yaml test suite'
|
||||
}
|
||||
});
|
||||
|
||||
if (process.argv.indexOf('help') + process.argv.indexOf('--help') + process.argv.indexOf('-h') !== -3) {
|
||||
@ -43,6 +68,7 @@ if (process.env.npm_config_argv) {
|
||||
}
|
||||
|
||||
var commands = [];
|
||||
var command;
|
||||
|
||||
if (argv['just-browser']) {
|
||||
argv.server = false;
|
||||
@ -50,12 +76,16 @@ if (argv['just-browser']) {
|
||||
}
|
||||
|
||||
if (argv['check-upstream']) {
|
||||
commands.push(['node', 'scripts/generate/yaml_tests/index.js']);
|
||||
command = ['node', 'scripts/generate/yaml_tests/index.js'];
|
||||
if (argv.force) {
|
||||
command.push('--force');
|
||||
}
|
||||
commands.push(command);
|
||||
}
|
||||
|
||||
if (argv.unit) {
|
||||
if (argv.server) {
|
||||
commands.push(['mocha', 'test/unit/test_*.js', '--require=should']);
|
||||
commands.push(['mocha', 'test/unit/test_*.js', '--require should']);
|
||||
}
|
||||
if (argv.browsers) {
|
||||
commands.push(['testling', '.']);
|
||||
|
||||
@ -109,7 +109,11 @@ HttpConnector.prototype.request = function (params, cb) {
|
||||
}
|
||||
|
||||
log.trace(params.method, reqParams, params.body, response, status);
|
||||
cb(err, response, status);
|
||||
if (err) {
|
||||
cb(err);
|
||||
} else {
|
||||
cb(err, response, status);
|
||||
}
|
||||
}, this);
|
||||
|
||||
request = this.hand.request(reqParams, function (_incoming) {
|
||||
|
||||
@ -12,7 +12,7 @@ function LoggerAbstract(log, config) {
|
||||
_.makeBoundMethods(this);
|
||||
|
||||
// when the log closes, remove our event listeners
|
||||
this.log.on('closing', this.bound.cleanUpListeners);
|
||||
this.log.once('closing', this.bound.cleanUpListeners);
|
||||
|
||||
this.setupListeners(config.levels);
|
||||
}
|
||||
@ -62,14 +62,15 @@ LoggerAbstract.prototype.write = function () {
|
||||
LoggerAbstract.prototype.setupListeners = function (levels) {
|
||||
this.cleanUpListeners();
|
||||
|
||||
this.listeningLevels = levels;
|
||||
this.listeningLevels = [];
|
||||
|
||||
_.each(this.listeningLevels, function (level) {
|
||||
_.each(levels, function (level) {
|
||||
var fnName = 'on' + _.ucfirst(level);
|
||||
if (this.bound[fnName]) {
|
||||
this.listeningLevels.push(level);
|
||||
this.log.on(level, this.bound[fnName]);
|
||||
} else {
|
||||
throw new Error(fnName + ' is not a function');
|
||||
throw new Error('Unable to listen for level "' + level + '"');
|
||||
}
|
||||
}, this);
|
||||
};
|
||||
@ -144,7 +145,7 @@ LoggerAbstract.prototype.onDebug = _.handler(function (msg) {
|
||||
* @return {undefined}
|
||||
*/
|
||||
LoggerAbstract.prototype.onTrace = _.handler(function (message, curlCall) {
|
||||
this.write('TRACE', message + '\n' + curlCall);
|
||||
this.write('TRACE', curlCall + '\n' + message);
|
||||
});
|
||||
|
||||
|
||||
|
||||
@ -20,24 +20,11 @@ var LoggerAbstract = require('../logger');
|
||||
var _ = require('../utils');
|
||||
|
||||
var defaultColors = {
|
||||
error: function (txt) {
|
||||
return chalk.red.bold(txt);
|
||||
},
|
||||
warning: function (txt) {
|
||||
return chalk.yellow.bold(txt);
|
||||
},
|
||||
info: function (txt) {
|
||||
return chalk.cyan.bold(txt);
|
||||
},
|
||||
debug: function (txt) {
|
||||
return chalk.magenta.bold(txt);
|
||||
},
|
||||
trace: function (txt) {
|
||||
return chalk.white.bold(txt);
|
||||
},
|
||||
traceStatus: function (status) {
|
||||
return chalk[status >= 200 && status < 300 ? 'green' : 'red'].bold(status);
|
||||
}
|
||||
error: chalk.red.bold,
|
||||
warning: chalk.yellow.bold,
|
||||
info: chalk.cyan.bold,
|
||||
debug: chalk.magenta.bold,
|
||||
trace: chalk.white.bold
|
||||
};
|
||||
|
||||
function Stdio(log, config) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Logger that writes to a file
|
||||
*
|
||||
* @class Loggers.File
|
||||
* @class Loggers.Stream
|
||||
* @extends LoggerAbstract
|
||||
* @constructor
|
||||
* @see LoggerAbstract
|
||||
@ -16,7 +16,6 @@ var LoggerAbstract = require('../logger');
|
||||
var _ = require('../utils');
|
||||
|
||||
function Stream(log, config) {
|
||||
// call my super
|
||||
LoggerAbstract.call(this, log, config);
|
||||
|
||||
if (config.stream && config.stream.write && config.stream.end) {
|
||||
@ -25,22 +24,21 @@ function Stream(log, config) {
|
||||
throw new TypeError('Invalid stream, use an instance of stream.Writeable');
|
||||
}
|
||||
|
||||
if (this.stream._writableState && this.stream._writableState.buffer) {
|
||||
process.on('exit', this.bound.onProcessExit);
|
||||
}
|
||||
// else you should probably flush your stream
|
||||
process.once('exit', this.bound.onProcessExit);
|
||||
}
|
||||
_.inherits(Stream, LoggerAbstract);
|
||||
|
||||
// flush the write buffer to stderr synchronously
|
||||
Stream.prototype.onProcessExit = _.handler(function () {
|
||||
// process is dying, lets manually flush the buffer synchronously to stderr.
|
||||
var writeBuffer = this.stream._writableState.buffer;
|
||||
if (writeBuffer && writeBuffer.length) {
|
||||
console.error('Log stream did not get to finish writing. Flushing to stderr');
|
||||
writeBuffer.forEach(function (buffered) {
|
||||
console.error(buffered.chunk.toString());
|
||||
});
|
||||
if (this.stream._writableState && this.stream._writableState.buffer) {
|
||||
var writeBuffer = this.stream._writableState.buffer;
|
||||
if (writeBuffer.length) {
|
||||
console.error('Log stream did not get to finish writing. Flushing to stderr');
|
||||
writeBuffer.forEach(function (buffered) {
|
||||
console.error(buffered.chunk.toString());
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -1,20 +1,25 @@
|
||||
var _ = require('./utils');
|
||||
var extractHostPartsRE = /\[([^:]+):(\d+)\]/;
|
||||
var extractHostPartsRE = /\[\/*([^:]+):(\d+)\]/;
|
||||
|
||||
module.exports = function (nodes) {
|
||||
var hosts = [];
|
||||
_.each(nodes, function (node, id) {
|
||||
var hostnameMatches = extractHostPartsRE.exec(node.http_address);
|
||||
hosts.push({
|
||||
host: hostnameMatches[1],
|
||||
port: hostnameMatches[2],
|
||||
_meta: {
|
||||
id: id,
|
||||
name: node.name,
|
||||
hostname: node.hostname,
|
||||
version: node.version
|
||||
}
|
||||
function makeNodeParser(hostProp) {
|
||||
return function (nodes) {
|
||||
var hosts = [];
|
||||
_.each(nodes, function (node, id) {
|
||||
var hostnameMatches = extractHostPartsRE.exec(node[hostProp]);
|
||||
hosts.push({
|
||||
host: hostnameMatches[1],
|
||||
port: parseInt(hostnameMatches[2], 10),
|
||||
_meta: {
|
||||
id: id,
|
||||
name: node.name,
|
||||
hostname: node.hostname,
|
||||
version: node.version
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
return hosts;
|
||||
};
|
||||
return hosts;
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = makeNodeParser('http_address');
|
||||
module.exports.thrift = makeNodeParser('transport_address');
|
||||
|
||||
@ -28,6 +28,9 @@ function Transport(config) {
|
||||
var Serializer = _.funcEnum(config, 'serializer', Transport.serializers, 'json');
|
||||
this.serializer = new Serializer(config);
|
||||
|
||||
// setup the nodesToHostCallback
|
||||
this.nodesToHostCallback = _.funcEnum(config, 'nodesToHostCallback', Transport.nodesToHostCallbacks, 'main');
|
||||
|
||||
// setup max retries
|
||||
this.maxRetries = config.hasOwnProperty('maxRetries') ? config.maxRetries : 3;
|
||||
|
||||
@ -209,7 +212,8 @@ Transport.prototype.createDefer = function () {
|
||||
* @param {Function} cb - Function to call back once complete
|
||||
*/
|
||||
Transport.prototype.sniff = function (cb) {
|
||||
var self = this;
|
||||
var connectionPool = this.connectionPool;
|
||||
var nodesToHostCallback = this.nodesToHostCallback;
|
||||
|
||||
// make cb a function if it isn't
|
||||
cb = typeof cb === 'function' ? cb : _.noop;
|
||||
@ -217,14 +221,14 @@ Transport.prototype.sniff = function (cb) {
|
||||
this.request({
|
||||
path: '/_cluster/nodes',
|
||||
method: 'GET'
|
||||
}, function (err, resp) {
|
||||
}, function (err, resp, status) {
|
||||
if (!err && resp && resp.nodes) {
|
||||
var hosts = _.map(self.nodesToHostCallback(resp.nodes), function (hostConfig) {
|
||||
var hosts = _.map(nodesToHostCallback(resp.nodes), function (hostConfig) {
|
||||
return new Host(hostConfig);
|
||||
});
|
||||
this.connectionPool.setHosts(hosts);
|
||||
connectionPool.setHosts(hosts);
|
||||
}
|
||||
cb(err, resp);
|
||||
cb(err, resp, status);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
16
test/fixtures/short_node_list.json
vendored
Normal file
16
test/fixtures/short_node_list.json
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"id1": {
|
||||
"name": "Headknocker",
|
||||
"transport_address": "inet[/10.10.10.100:9300]",
|
||||
"hostname": "Spencers-MacBook-Pro.local",
|
||||
"version": "0.90.5",
|
||||
"http_address": "inet[/10.10.10.100:9205]"
|
||||
},
|
||||
"id2": {
|
||||
"name": "Buttknocker",
|
||||
"transport_address": "inet[/10.10.10.101:9300]",
|
||||
"hostname": "Johns-MacBook-Pro.local",
|
||||
"version": "0.90.5",
|
||||
"http_address": "inet[/10.10.10.101:9205]"
|
||||
}
|
||||
}
|
||||
32
test/mocks/incomming_message.js
Normal file
32
test/mocks/incomming_message.js
Normal file
@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Simple Mock of the http.IncommingMessage. Just implmenents the methods the methods
|
||||
* we use
|
||||
*
|
||||
* @type {[type]}
|
||||
*/
|
||||
module.exports = MockIncommingMessage;
|
||||
|
||||
var sinon = require('sinon');
|
||||
var util = require('util');
|
||||
var Readable = require('stream').Readable;
|
||||
|
||||
function MockIncommingMessage() {
|
||||
var self = this;
|
||||
|
||||
Readable.call(self);
|
||||
|
||||
self.setEncoding = sinon.stub();
|
||||
self._read = function () {};
|
||||
}
|
||||
util.inherits(MockIncommingMessage, Readable);
|
||||
|
||||
/**
|
||||
* To make the message "talk" do something like this:
|
||||
*
|
||||
* process.nextTick(function () {
|
||||
* if (resp) {
|
||||
* incom.push(chunk);
|
||||
* }
|
||||
* incom.push(null);
|
||||
* });
|
||||
*/
|
||||
12
test/mocks/request.js
Normal file
12
test/mocks/request.js
Normal file
@ -0,0 +1,12 @@
|
||||
module.exports = MockRequest;
|
||||
|
||||
var sinon = require('sinon');
|
||||
var util = require('util');
|
||||
var http = require('http');
|
||||
|
||||
function MockRequest() {
|
||||
sinon.stub(this, 'end');
|
||||
sinon.stub(this, 'write');
|
||||
this.log = sinon.stub(this.log);
|
||||
}
|
||||
util.inherits(MockRequest, http.ClientRequest);
|
||||
18
test/mocks/writable_stream.js
Normal file
18
test/mocks/writable_stream.js
Normal file
@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Just a buffer really, but one that implements the Writeable class
|
||||
* @type {WritableStream}
|
||||
*/
|
||||
module.exports = MockWritableStream;
|
||||
|
||||
var Writable = require('stream').Writable;
|
||||
var util = require('util');
|
||||
|
||||
function MockWritableStream(opts) {
|
||||
Writable.call(this, opts);
|
||||
|
||||
this._write = function (chunk, encoding, cb) {
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
util.inherits(MockWritableStream, Writable);
|
||||
@ -3,6 +3,14 @@ var Host = require('../../src/lib/host');
|
||||
var sinon = require('sinon');
|
||||
var _ = require('lodash');
|
||||
|
||||
var stubs = [];
|
||||
afterEach(function () {
|
||||
var stub;
|
||||
while (stub = stubs.pop()) {
|
||||
stub.restore();
|
||||
}
|
||||
});
|
||||
|
||||
describe('Connection Abstract', function () {
|
||||
var host = new Host('localhost:9200');
|
||||
|
||||
@ -75,6 +83,7 @@ describe('Connection Abstract', function () {
|
||||
|
||||
it('sets a timeout when set to dead, and removed when alive', function () {
|
||||
var clock = sinon.useFakeTimers('setTimeout', 'clearTimeout');
|
||||
stubs.push(clock);
|
||||
var conn = new ConnectionAbstract(host);
|
||||
|
||||
var start = _.size(clock.timeouts);
|
||||
@ -103,6 +112,7 @@ describe('Connection Abstract', function () {
|
||||
it('should ping the connection after the deadTimeout, and set the status to "alive" on pong', function (done) {
|
||||
var conn = new ConnectionAbstract(host);
|
||||
var clock = sinon.useFakeTimers('setTimeout', 'clearTimeout');
|
||||
stubs.push(clock);
|
||||
|
||||
// schedules the resuscitate
|
||||
conn.setStatus('dead');
|
||||
@ -128,6 +138,7 @@ describe('Connection Abstract', function () {
|
||||
it('should ping the connection after the deadTimeout, and set the status to "dead" on error', function (done) {
|
||||
var conn = new ConnectionAbstract(host);
|
||||
var clock = sinon.useFakeTimers('setTimeout', 'clearTimeout');
|
||||
stubs.push(clock);
|
||||
|
||||
// schedules the resuscitate
|
||||
conn.setStatus('dead');
|
||||
@ -142,7 +153,6 @@ describe('Connection Abstract', function () {
|
||||
// will be called after the ping calls back
|
||||
conn.setStatus = function (status) {
|
||||
status.should.eql('dead');
|
||||
clock.restore();
|
||||
done();
|
||||
};
|
||||
|
||||
|
||||
@ -2,8 +2,70 @@ describe('Http Connector', function () {
|
||||
|
||||
var should = require('should');
|
||||
var Host = require('../../src/lib/host');
|
||||
var errors = require('../../src/lib/errors');
|
||||
var HttpConnection = require('../../src/lib/connectors/http');
|
||||
var ConnectionAbstract = require('../../src/lib/connection');
|
||||
var nock = require('nock');
|
||||
var sinon = require('sinon');
|
||||
var util = require('util');
|
||||
|
||||
var http = require('http');
|
||||
var https = require('https');
|
||||
|
||||
var MockRequest = require('../mocks/request');
|
||||
var MockIncommingMessage = require('../mocks/incomming_message');
|
||||
|
||||
nock.disableNetConnect();
|
||||
|
||||
afterEach(function () {
|
||||
if (http.request.restore) {
|
||||
http.request.restore();
|
||||
}
|
||||
if (https.request.restore) {
|
||||
https.request.restore();
|
||||
}
|
||||
});
|
||||
|
||||
function makeStubReqMethod(prep) {
|
||||
return function (params, cb) {
|
||||
var req = new MockRequest();
|
||||
if (prep) {
|
||||
prep(req, params, cb);
|
||||
}
|
||||
return req;
|
||||
};
|
||||
}
|
||||
|
||||
function whereReqDies(withErr) {
|
||||
return function (req) {
|
||||
process.nextTick(function () {
|
||||
// causes the request to quit and callback
|
||||
req.emit('error', withErr || void 0);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function whichMocksMessage(prep) {
|
||||
return function (req, params, cb) {
|
||||
process.nextTick(function () {
|
||||
var incom = new MockIncommingMessage();
|
||||
if (prep) {
|
||||
prep(incom);
|
||||
}
|
||||
cb(incom);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function whichErrorsAfterPartialBody(err) {
|
||||
return function (incom) {
|
||||
incom.statusCode = 200;
|
||||
incom.push('{ "hits": { "hits": { "hits": { "hits": { "hits": { "hits": ');
|
||||
setTimeout(function () {
|
||||
incom.emit('error', err || new Error('Socket is dead now...'));
|
||||
}, 20);
|
||||
};
|
||||
}
|
||||
|
||||
describe('Constructor', function () {
|
||||
it('creates an object that extends ConnectionAbstract', function () {
|
||||
@ -30,7 +92,6 @@ describe('Http Connector', function () {
|
||||
});
|
||||
|
||||
describe('#makeReqParams', function () {
|
||||
|
||||
it('properly reads the host object', function () {
|
||||
var host = new Host('john:dude@pizza.com:9200/pizza/cheese?shrooms=true');
|
||||
var con = new HttpConnection(host, {});
|
||||
@ -133,35 +194,9 @@ describe('Http Connector', function () {
|
||||
});
|
||||
|
||||
describe('#request', function () {
|
||||
var http = require('http');
|
||||
var https = require('https');
|
||||
var sinon = require('sinon');
|
||||
var util = require('util');
|
||||
|
||||
function FakeRequest() {
|
||||
sinon.stub(this, 'end');
|
||||
sinon.stub(this, 'write');
|
||||
this.log = sinon.stub(this.log);
|
||||
}
|
||||
util.inherits(FakeRequest, http.ClientRequest);
|
||||
|
||||
function reqMethodStub(params, cb) {
|
||||
var req = new FakeRequest();
|
||||
process.nextTick(function () {
|
||||
// causes the request to quit and callback
|
||||
req.emit('error');
|
||||
});
|
||||
return req;
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
sinon.stub(http, 'request', reqMethodStub);
|
||||
sinon.stub(https, 'request', reqMethodStub);
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
http.request.restore();
|
||||
https.request.restore();
|
||||
sinon.stub(http, 'request', makeStubReqMethod(whereReqDies()));
|
||||
sinon.stub(https, 'request', makeStubReqMethod(whereReqDies()));
|
||||
});
|
||||
|
||||
it('calls http based on the host', function (done) {
|
||||
@ -188,14 +223,7 @@ describe('Http Connector', function () {
|
||||
sinon.stub(con.log);
|
||||
|
||||
http.request.restore();
|
||||
sinon.stub(http, 'request', function (params, cb) {
|
||||
var req = new FakeRequest();
|
||||
process.nextTick(function () {
|
||||
// causes the request to quit and callback
|
||||
req.emit('error', new Error('actual error'));
|
||||
});
|
||||
return req;
|
||||
});
|
||||
sinon.stub(http, 'request', makeStubReqMethod(whereReqDies(new Error('actual error'))));
|
||||
|
||||
con.request({}, function (err) {
|
||||
// error should have been sent to the
|
||||
@ -221,14 +249,7 @@ describe('Http Connector', function () {
|
||||
sinon.stub(con.log);
|
||||
|
||||
http.request.restore();
|
||||
sinon.stub(http, 'request', function (params, cb) {
|
||||
var req = new FakeRequest();
|
||||
process.nextTick(function () {
|
||||
// causes the request to quit and callback
|
||||
req.emit('error', new Error('actual error'));
|
||||
});
|
||||
return req;
|
||||
});
|
||||
sinon.stub(http, 'request', makeStubReqMethod(whereReqDies(new Error('actual error'))));
|
||||
|
||||
con.request({}, function (err) {
|
||||
// error should have been sent to the
|
||||
@ -246,25 +267,70 @@ describe('Http Connector', function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Request Implementation', function () {
|
||||
var server;
|
||||
var nock = require('nock');
|
||||
nock.disableNetConnect();
|
||||
var host = new Host('http://esjs.com:9200');
|
||||
describe('#request with incomming message error', function () {
|
||||
function makeStubReqWithMsgWhichErrorsMidBody(err) {
|
||||
return makeStubReqMethod(whichMocksMessage(whichErrorsAfterPartialBody(err)));
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
server = nock('http://esjs.com:9200');
|
||||
it('logs error event', function (done) {
|
||||
var con = new HttpConnection(new Host('https://google.com'));
|
||||
sinon.stub(con.log, 'error');
|
||||
sinon.stub(https, 'request', makeStubReqWithMsgWhichErrorsMidBody());
|
||||
|
||||
con.request({}, function (err, resp, status) {
|
||||
con.log.error.callCount.should.eql(1);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
server.done();
|
||||
nock.restore();
|
||||
it('and sets the connection to dead', function (done) {
|
||||
var con = new HttpConnection(new Host('https://google.com'));
|
||||
sinon.stub(https, 'request', makeStubReqWithMsgWhichErrorsMidBody());
|
||||
|
||||
con.request({}, function (err, resp, status) {
|
||||
con.status.should.eql('dead');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('passes the original error on', function (done) {
|
||||
var con = new HttpConnection(new Host('https://google.com'));
|
||||
sinon.stub(https, 'request', makeStubReqWithMsgWhichErrorsMidBody(new Error('no more message :(')));
|
||||
|
||||
con.request({}, function (err, resp, status) {
|
||||
should.exist(err);
|
||||
err.message.should.eql('no more message :(');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('does not pass the partial body along', function (done) {
|
||||
var con = new HttpConnection(new Host('https://google.com'));
|
||||
sinon.stub(https, 'request', makeStubReqWithMsgWhichErrorsMidBody());
|
||||
|
||||
con.request({}, function (err, resp, status) {
|
||||
should.not.exist(resp);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('does not pass the status code along', function (done) {
|
||||
var con = new HttpConnection(new Host('https://google.com'));
|
||||
sinon.stub(https, 'request', makeStubReqWithMsgWhichErrorsMidBody());
|
||||
|
||||
con.request({}, function (err, resp, status) {
|
||||
should.not.exist(status);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#request\'s responder', function () {
|
||||
it('collects the whole request body', function (done) {
|
||||
var con = new HttpConnection(host);
|
||||
|
||||
var server = nock('http://esjs.com:9200');
|
||||
var con = new HttpConnection(new Host('http://esjs.com:9200'));
|
||||
var body = '{ "USER": "doc" }';
|
||||
|
||||
server
|
||||
.get('/users/1')
|
||||
.reply(200, body);
|
||||
@ -273,34 +339,34 @@ describe('Http Connector', function () {
|
||||
method: 'GET',
|
||||
path: '/users/1'
|
||||
}, function (err, resp, status) {
|
||||
should(err).not.exist;
|
||||
should.not.exist(err);
|
||||
resp.should.eql(body);
|
||||
status.should.eql(200);
|
||||
server.done();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Catches network errors and passes back the error', function () {
|
||||
var con = new HttpConnection(host);
|
||||
it('Ignores serialization errors', function (done) {
|
||||
var server = nock('http://esjs.com:9200');
|
||||
var con = new HttpConnection(new Host('http://esjs.com:9200'));
|
||||
var body = '{ "USER":';
|
||||
|
||||
var body = '{ "USER": "doc" }';
|
||||
// partial body
|
||||
server
|
||||
.get('/users/1')
|
||||
.reply(200, {
|
||||
|
||||
});
|
||||
.reply(200, body);
|
||||
|
||||
con.request({
|
||||
method: 'GET',
|
||||
path: '/users/1'
|
||||
}, function (err, resp, status) {
|
||||
should(err).not.exist;
|
||||
should.not.exist(err);
|
||||
resp.should.eql(body);
|
||||
status.should.eql(200);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
250
test/unit/test_logger.js
Normal file
250
test/unit/test_logger.js
Normal file
@ -0,0 +1,250 @@
|
||||
describe('Logger Abstract', function () {
|
||||
|
||||
var sinon = require('sinon');
|
||||
var now = new Date('2013-03-01T00:00:00Z');
|
||||
var Log = require('../../src/lib/log');
|
||||
var LoggerAbstract = require('../../src/lib/logger');
|
||||
|
||||
var parentLog;
|
||||
var stubs = [];
|
||||
|
||||
function stub() {
|
||||
stubs.push(sinon.stub.apply(sinon, arguments));
|
||||
}
|
||||
|
||||
function makeLogger(levels) {
|
||||
return new LoggerAbstract(parentLog, {
|
||||
levels: levels || []
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
parentLog = new Log();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
var stub;
|
||||
while (stub = stubs.pop()) {
|
||||
stub.restore();
|
||||
}
|
||||
|
||||
parentLog.close();
|
||||
});
|
||||
|
||||
describe('Constuctor', function () {
|
||||
it('calls setupListeners', function () {
|
||||
stub(LoggerAbstract.prototype, 'setupListeners');
|
||||
var logger = makeLogger();
|
||||
logger.setupListeners.callCount.should.eql(1);
|
||||
});
|
||||
|
||||
it('listens for the loggers\' "closing" event', function () {
|
||||
var logger = makeLogger();
|
||||
parentLog.listenerCount('closing').should.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setupListeners', function () {
|
||||
it('calls cleanUpListeners', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'cleanUpListeners');
|
||||
logger.setupListeners([]);
|
||||
logger.cleanUpListeners.callCount.should.eql(1);
|
||||
});
|
||||
|
||||
it('explicitly listens for the events specified', function () {
|
||||
var logger = makeLogger();
|
||||
logger.setupListeners(['error']);
|
||||
parentLog.listenerCount('error').should.eql(1);
|
||||
parentLog.listenerCount('warning').should.eql(0);
|
||||
parentLog.listenerCount('info').should.eql(0);
|
||||
parentLog.listenerCount('debug').should.eql(0);
|
||||
parentLog.listenerCount('trace').should.eql(0);
|
||||
|
||||
logger.setupListeners(['warning', 'trace']);
|
||||
parentLog.listenerCount('error').should.eql(0);
|
||||
parentLog.listenerCount('warning').should.eql(1);
|
||||
parentLog.listenerCount('info').should.eql(0);
|
||||
parentLog.listenerCount('debug').should.eql(0);
|
||||
parentLog.listenerCount('trace').should.eql(1);
|
||||
|
||||
logger.setupListeners(['debug', 'debug']);
|
||||
parentLog.listenerCount('error').should.eql(0);
|
||||
parentLog.listenerCount('warning').should.eql(0);
|
||||
parentLog.listenerCount('info').should.eql(0);
|
||||
parentLog.listenerCount('debug').should.eql(2);
|
||||
parentLog.listenerCount('trace').should.eql(0);
|
||||
});
|
||||
|
||||
it('sets the logLevel property to the new levels', function () {
|
||||
var logger = makeLogger();
|
||||
var levels = ['error'];
|
||||
logger.setupListeners(levels);
|
||||
logger.listeningLevels.should.eql(levels).and.not.be.exactly(levels);
|
||||
|
||||
levels = ['warning', 'trace'];
|
||||
logger.setupListeners(levels);
|
||||
logger.listeningLevels.should.eql(levels).and.not.be.exactly(levels);
|
||||
|
||||
|
||||
levels = ['debug', 'debug'];
|
||||
logger.setupListeners(levels);
|
||||
logger.listeningLevels.should.eql(levels).and.not.be.exactly(levels);
|
||||
});
|
||||
|
||||
it('rejects listening levels it can not listen to', function () {
|
||||
var logger = makeLogger();
|
||||
(function () {
|
||||
logger.setupListeners(['scream']);
|
||||
}).should.throw(/unable to listen/i);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#timestamp', function () {
|
||||
it('returns in the right format', function () {
|
||||
stubs.push(sinon.useFakeTimers(now.getTime()));
|
||||
var logger = makeLogger();
|
||||
logger.timestamp().should.eql('2013-03-01T00:00:00Z');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#formate', function () {
|
||||
it('returns a single string with the message indented', function () {
|
||||
stubs.push(sinon.useFakeTimers(now.getTime()));
|
||||
var logger = makeLogger();
|
||||
logger.format('LABEL', 'MSG').should.eql(
|
||||
'LABEL: 2013-03-01T00:00:00Z\n' +
|
||||
' MSG\n' +
|
||||
'\n'
|
||||
);
|
||||
});
|
||||
|
||||
it('properly indents multi-line messages', function () {
|
||||
stubs.push(sinon.useFakeTimers(now.getTime()));
|
||||
var logger = makeLogger();
|
||||
logger.format('LABEL', 'MSG\nwith\nseveral lines').should.eql(
|
||||
'LABEL: 2013-03-01T00:00:00Z\n' +
|
||||
' MSG\n' +
|
||||
' with\n' +
|
||||
' several lines\n' +
|
||||
'\n'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#write', function () {
|
||||
it('requires that it is overwritten', function () {
|
||||
(function () {
|
||||
var logger = makeLogger();
|
||||
logger.write();
|
||||
}).should.throw(/overwritten/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#onError', function () {
|
||||
it('uses the Error name when it is not just "Error"', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (label, msg) {
|
||||
label.should.eql('TypeError');
|
||||
});
|
||||
|
||||
logger.onError(new TypeError('Typerr'));
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
|
||||
it('uses "ERROR" when the error name is "Error"', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (label, msg) {
|
||||
label.should.eql('ERROR');
|
||||
});
|
||||
|
||||
logger.onError(new Error('thing'));
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#onWarning', function () {
|
||||
it('uses the "WARNING" label', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (label, msg) {
|
||||
label.should.eql('WARNING');
|
||||
});
|
||||
logger.onWarning('message');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
|
||||
it('echos the message', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (label, msg) {
|
||||
msg.should.eql('message');
|
||||
});
|
||||
|
||||
logger.onWarning('message');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#onInfo', function () {
|
||||
it('uses the "INFO" label', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (label, msg) {
|
||||
label.should.eql('INFO');
|
||||
});
|
||||
logger.onInfo('message');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
|
||||
it('echos the message', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (label, msg) {
|
||||
msg.should.eql('message');
|
||||
});
|
||||
|
||||
logger.onInfo('message');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#onDebug', function () {
|
||||
it('uses the "DEBUG" label', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (label, msg) {
|
||||
label.should.eql('DEBUG');
|
||||
});
|
||||
logger.onDebug('message');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
|
||||
it('echos the message', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (label, msg) {
|
||||
msg.should.eql('message');
|
||||
});
|
||||
|
||||
logger.onDebug('message');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#onTrace', function () {
|
||||
it('uses the "TRACE" label', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (label, msg) {
|
||||
label.should.eql('TRACE');
|
||||
});
|
||||
logger.onTrace('message');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
|
||||
it('joins the message and curl call with a newline', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (label, msg) {
|
||||
msg.should.eql('curlcall\nmessage');
|
||||
});
|
||||
|
||||
logger.onTrace('message', 'curlcall');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
32
test/unit/test_nodes_to_host_callback.js
Normal file
32
test/unit/test_nodes_to_host_callback.js
Normal file
@ -0,0 +1,32 @@
|
||||
describe('Nodes to host callback', function () {
|
||||
var callback = require('../../src/lib/nodes_to_host');
|
||||
|
||||
// example node list that would come back from "GET _cluster/nodes"
|
||||
var nodes = require('../fixtures/short_node_list.json');
|
||||
|
||||
it('properly creates host objects', function () {
|
||||
var hosts = callback(nodes);
|
||||
hosts.should.have.lengthOf(2);
|
||||
hosts[0].should.eql({
|
||||
host: '10.10.10.100',
|
||||
port: 9205,
|
||||
_meta: {
|
||||
id: 'id1',
|
||||
name: 'Headknocker',
|
||||
hostname: 'Spencers-MacBook-Pro.local',
|
||||
version: '0.90.5'
|
||||
}
|
||||
});
|
||||
hosts[1].should.eql({
|
||||
host: '10.10.10.101',
|
||||
port: 9205,
|
||||
_meta: {
|
||||
id: 'id2',
|
||||
name: 'Buttknocker',
|
||||
hostname: 'Johns-MacBook-Pro.local',
|
||||
version: '0.90.5'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@ -1,71 +1,212 @@
|
||||
|
||||
var es = require('../../src/elasticsearch');
|
||||
var Log = require('../../src/lib/log');
|
||||
var StdioLogger = require('../../src/lib/loggers/stdio');
|
||||
var _ = require('../../src/lib/utils');
|
||||
var expect = require('expect.js');
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
var sinon = require('sinon');
|
||||
var stubs = [];
|
||||
var parentLog;
|
||||
|
||||
beforeEach(function () {
|
||||
parentLog = new Log();
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
var stub;
|
||||
while (stub = stubs.pop()) {
|
||||
stub.restore();
|
||||
}
|
||||
parentLog.close();
|
||||
});
|
||||
|
||||
function stub() {
|
||||
stubs.push(sinon.stub.apply(sinon, arguments));
|
||||
}
|
||||
|
||||
function makeLogger(colors) {
|
||||
var config = {
|
||||
levels: Log.parseLevels('trace')
|
||||
};
|
||||
if (colors !== void 0) {
|
||||
config.colors = colors;
|
||||
}
|
||||
return new StdioLogger(parentLog, config);
|
||||
}
|
||||
|
||||
describe('Stdio Logger', function () {
|
||||
var log, logger;
|
||||
|
||||
// pulled from chalk's stripColor function.
|
||||
var hasColorRE = /\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]/;
|
||||
|
||||
function listenerCount(emitter, event) {
|
||||
if (EventEmitter.listenerCount) {
|
||||
return EventEmitter.listenerCount(emitter, event);
|
||||
} else {
|
||||
return emitter.listeners(event).length;
|
||||
}
|
||||
}
|
||||
|
||||
describe('pays attention to the level setting', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
log = new Log();
|
||||
|
||||
log.emit = function (name/*, ...args */) {
|
||||
log._emission = {
|
||||
name: name,
|
||||
args: Array.prototype.slice(arguments, 1)
|
||||
};
|
||||
};
|
||||
|
||||
// new logger in warning mode
|
||||
logger = new StdioLogger(log, {
|
||||
levels: Log.parseLevels('trace')
|
||||
});
|
||||
var logger = makeLogger();
|
||||
stub(parentLog, 'emit');
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
log.close();
|
||||
});
|
||||
|
||||
it('listenes for all the events', function () {
|
||||
listenerCount(log, 'error').should.eql(1);
|
||||
listenerCount(log, 'warning').should.eql(1);
|
||||
listenerCount(log, 'info').should.eql(1);
|
||||
listenerCount(log, 'debug').should.eql(1);
|
||||
listenerCount(log, 'trace').should.eql(1);
|
||||
it('listens for all the events', function () {
|
||||
parentLog.listenerCount('error').should.eql(1);
|
||||
parentLog.listenerCount('warning').should.eql(1);
|
||||
parentLog.listenerCount('info').should.eql(1);
|
||||
parentLog.listenerCount('debug').should.eql(1);
|
||||
parentLog.listenerCount('trace').should.eql(1);
|
||||
});
|
||||
|
||||
it('emits events because something is listening', function () {
|
||||
log.error(new Error('error message'));
|
||||
log._emission.name.should.eql('error');
|
||||
parentLog.error(new Error('error message'));
|
||||
parentLog.emit.lastCall.args[0].should.eql('error');
|
||||
|
||||
log.warning('warning');
|
||||
log._emission.name.should.eql('warning');
|
||||
parentLog.warning('warning');
|
||||
parentLog.emit.lastCall.args[0].should.eql('warning');
|
||||
|
||||
log.info('info');
|
||||
log._emission.name.should.eql('info');
|
||||
parentLog.info('info');
|
||||
parentLog.emit.lastCall.args[0].should.eql('info');
|
||||
|
||||
log.debug('debug');
|
||||
log._emission.name.should.eql('debug');
|
||||
parentLog.debug('debug');
|
||||
parentLog.emit.lastCall.args[0].should.eql('debug');
|
||||
|
||||
log.trace('GET', {}, '', '', 200);
|
||||
log._emission.name.should.eql('trace');
|
||||
parentLog.trace('GET', {}, '', '', 200);
|
||||
parentLog.emit.lastCall.args[0].should.eql('trace');
|
||||
});
|
||||
});
|
||||
|
||||
describe('colorizing', function () {
|
||||
var chalk = require('chalk');
|
||||
var now = '2013-01-01T00:00:00Z';
|
||||
var nowDate = new Date(now);
|
||||
var nowTime = nowDate.getTime();
|
||||
var clock;
|
||||
|
||||
beforeEach(function () {
|
||||
stubs.push(sinon.useFakeTimers(nowTime));
|
||||
});
|
||||
|
||||
it('uses colors when it\'s supported', function () {
|
||||
var logger = makeLogger();
|
||||
var hasColor = require('chalk').supportsColor;
|
||||
logger.color.should.be.exactly(hasColor);
|
||||
});
|
||||
|
||||
it('obeys the logger.color === false', function () {
|
||||
var logger = makeLogger();
|
||||
stub(process.stdout, 'write');
|
||||
var withoutColor = 'INFO: ' + now + '\n something\n\n';
|
||||
|
||||
logger.color = false;
|
||||
logger.onInfo('something');
|
||||
process.stdout.write.lastCall.args[0].should.eql(withoutColor);
|
||||
});
|
||||
|
||||
it('obeys the logger.color === true', function () {
|
||||
var logger = makeLogger(false);
|
||||
stub(process.stdout, 'write');
|
||||
var withoutColor = 'TRACE: ' + now + '\n curl\n msg\n\n';
|
||||
|
||||
logger.color = true;
|
||||
logger.onTrace('msg', 'curl');
|
||||
process.stdout.write.lastCall.args[0].should.not.eql(withoutColor);
|
||||
chalk.stripColor(process.stdout.write.lastCall.args[0]).should.eql(withoutColor);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#onError', function () {
|
||||
it('uses the Error name when it is not just "Error"', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (to, label, colorize, msg) {
|
||||
label.should.eql('TypeError');
|
||||
});
|
||||
|
||||
logger.onError(new TypeError('Typerr'));
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
|
||||
it('uses "ERROR" when the error name is "Error"', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (to, label, colorize, msg) {
|
||||
label.should.eql('ERROR');
|
||||
});
|
||||
|
||||
logger.onError(new Error('thing'));
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#onWarning', function () {
|
||||
it('uses the "WARNING" label', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (to, label, colorize, msg) {
|
||||
label.should.eql('WARNING');
|
||||
});
|
||||
logger.onWarning('message');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
|
||||
it('echos the message', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (to, label, colorize, msg) {
|
||||
msg.should.eql('message');
|
||||
});
|
||||
|
||||
logger.onWarning('message');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#onInfo', function () {
|
||||
it('uses the "INFO" label', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (to, label, colorize, msg) {
|
||||
label.should.eql('INFO');
|
||||
});
|
||||
logger.onInfo('message');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
|
||||
it('echos the message', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (to, label, colorize, msg) {
|
||||
msg.should.eql('message');
|
||||
});
|
||||
|
||||
logger.onInfo('message');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#onDebug', function () {
|
||||
it('uses the "DEBUG" label', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (to, label, colorize, msg) {
|
||||
label.should.eql('DEBUG');
|
||||
});
|
||||
logger.onDebug('message');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
|
||||
it('echos the message', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (to, label, colorize, msg) {
|
||||
msg.should.eql('message');
|
||||
});
|
||||
|
||||
logger.onDebug('message');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#onTrace', function () {
|
||||
it('uses the "TRACE" label', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (to, label, colorize, msg) {
|
||||
label.should.eql('TRACE');
|
||||
});
|
||||
logger.onTrace('message');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
|
||||
it('joins the message and curl call with a newline', function () {
|
||||
var logger = makeLogger();
|
||||
stub(logger, 'write', function (to, label, colorize, msg) {
|
||||
msg.should.eql('curlcall\nmessage');
|
||||
});
|
||||
|
||||
logger.onTrace('message', 'curlcall');
|
||||
logger.write.callCount.should.eql(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
106
test/unit/test_stream_logger.js
Normal file
106
test/unit/test_stream_logger.js
Normal file
@ -0,0 +1,106 @@
|
||||
var Log = require('../../src/lib/log');
|
||||
var StreamLogger = require('../../src/lib/loggers/stream');
|
||||
var MockWritableStream = require('../mocks/writable_stream');
|
||||
var once = require('events').EventEmitter.prototype.once;
|
||||
var write = require('stream').Writable.prototype.write;
|
||||
var sinon = require('sinon');
|
||||
var stubs = [];
|
||||
var parentLog;
|
||||
var stream = new MockWritableStream();
|
||||
var _ = require('lodash');
|
||||
var util = require('util');
|
||||
|
||||
beforeEach(function () {
|
||||
parentLog = new Log();
|
||||
stub(stream, 'write', function () { console.log('stubbed write'); });
|
||||
stub(stream, 'end', function () { console.log('stubbed close'); });
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
parentLog.close();
|
||||
|
||||
var stub;
|
||||
while (stub = stubs.pop()) {
|
||||
stub.restore();
|
||||
}
|
||||
});
|
||||
|
||||
function stub() {
|
||||
stubs.push(sinon.stub.apply(sinon, arguments));
|
||||
}
|
||||
|
||||
function makeLogger() {
|
||||
var config = {
|
||||
levels: Log.parseLevels('trace'),
|
||||
stream: stream
|
||||
};
|
||||
return new StreamLogger(parentLog, config);
|
||||
}
|
||||
|
||||
describe('Stream Logger', function () {
|
||||
describe('pays attention to the level setting', function () {
|
||||
|
||||
beforeEach(function () {
|
||||
var logger = makeLogger();
|
||||
stub(parentLog, 'emit');
|
||||
});
|
||||
|
||||
it('listens for all the events', function () {
|
||||
parentLog.listenerCount('error').should.eql(1);
|
||||
parentLog.listenerCount('warning').should.eql(1);
|
||||
parentLog.listenerCount('info').should.eql(1);
|
||||
parentLog.listenerCount('debug').should.eql(1);
|
||||
parentLog.listenerCount('trace').should.eql(1);
|
||||
});
|
||||
|
||||
it('emits events because something is listening', function () {
|
||||
parentLog.error(new Error('error message'));
|
||||
parentLog.emit.lastCall.args[0].should.eql('error');
|
||||
|
||||
parentLog.warning('warning');
|
||||
parentLog.emit.lastCall.args[0].should.eql('warning');
|
||||
|
||||
parentLog.info('info');
|
||||
parentLog.emit.lastCall.args[0].should.eql('info');
|
||||
|
||||
parentLog.debug('debug');
|
||||
parentLog.emit.lastCall.args[0].should.eql('debug');
|
||||
|
||||
parentLog.trace('GET', {}, '', '', 200);
|
||||
parentLog.emit.lastCall.args[0].should.eql('trace');
|
||||
});
|
||||
});
|
||||
|
||||
describe('buffer flushing', function () {
|
||||
it('writes everything in the buffer to console.error', function () {
|
||||
var onExitCallback;
|
||||
sinon.stub(process, 'once', function (evName, cb) {
|
||||
if (evName === 'exit') {
|
||||
onExitCallback = cb;
|
||||
process.once.restore();
|
||||
} else {
|
||||
once.call(process, evName, cb);
|
||||
}
|
||||
});
|
||||
|
||||
var logger = makeLogger();
|
||||
var line = 'This string is repeated 10 times to create buffered output.\n';
|
||||
|
||||
_.times(10, function () {
|
||||
write.call(stream, line);
|
||||
});
|
||||
|
||||
var flushedOutput = '';
|
||||
sinon.stub(console, 'error', function (str) {
|
||||
flushedOutput += str;
|
||||
});
|
||||
onExitCallback();
|
||||
console.error.restore();
|
||||
// empty the buffer manually
|
||||
stream._writableState.buffer.splice(0);
|
||||
|
||||
flushedOutput.match(new RegExp(line, 'g')).length.should.above(0);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@ -1,9 +1,24 @@
|
||||
var Transport = require('../../src/lib/transport');
|
||||
var Host = require('../../src/lib/host');
|
||||
|
||||
var sinon = require('sinon');
|
||||
var nodeList = require('../fixtures/short_node_list.json');
|
||||
|
||||
var stubs = [];
|
||||
function stub() {
|
||||
stubs.push(sinon.stub.apply(sinon, arguments));
|
||||
}
|
||||
afterEach(function () {
|
||||
var stub;
|
||||
while (stub = stubs.pop()) {
|
||||
stub.restore();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
describe('Transport Class', function () {
|
||||
|
||||
describe('Constructor', function () {
|
||||
|
||||
it('Accepts a log class and intanciates it at this.log', function () {
|
||||
function CustomLogClass() {}
|
||||
var trans = new Transport({
|
||||
@ -73,7 +88,90 @@ describe('Transport Class', function () {
|
||||
});
|
||||
}).should.throw(/invalid logclass/i);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#sniff', function () {
|
||||
var trans;
|
||||
|
||||
beforeEach(function () {
|
||||
trans = new Transport();
|
||||
stub(trans, 'request', function (params, cb) {
|
||||
process.nextTick(function () {
|
||||
cb(void 0, {
|
||||
ok: true,
|
||||
cluster_name: 'clustername',
|
||||
nodes: nodeList
|
||||
}, 200);
|
||||
});
|
||||
});
|
||||
|
||||
stub(trans.connectionPool, 'setHosts');
|
||||
});
|
||||
|
||||
it('works without a callback', function (done) {
|
||||
trans.sniff();
|
||||
setTimeout(function () {
|
||||
trans.request.callCount.should.eql(1);
|
||||
done();
|
||||
}, 5);
|
||||
});
|
||||
|
||||
it('calls the nodesToHostCallback with the list of nodes', function (done) {
|
||||
trans.nodesToHostCallback = function (nodes) {
|
||||
nodes.should.eql(nodeList);
|
||||
done();
|
||||
return [];
|
||||
};
|
||||
trans.sniff();
|
||||
});
|
||||
|
||||
it('takes the host configs, converts them into Host objects, and passes them to connectionPool.setHosts',
|
||||
function (done) {
|
||||
trans.sniff(function () {
|
||||
trans.connectionPool.setHosts.callCount.should.eql(1);
|
||||
var hosts = trans.connectionPool.setHosts.lastCall.args[0];
|
||||
|
||||
hosts.should.have.length(2);
|
||||
|
||||
hosts[0].should.be.an.instanceOf(Host);
|
||||
hosts[0].host.should.eql('10.10.10.100');
|
||||
hosts[0].port.should.eql(9205);
|
||||
|
||||
hosts[0].should.be.an.instanceOf(Host);
|
||||
hosts[1].host.should.eql('10.10.10.101');
|
||||
hosts[1].port.should.eql(9205);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('passed back errors caught from the request', function (done) {
|
||||
trans.request.func = function (params, cb) {
|
||||
process.nextTick(function () {
|
||||
cb(new Error('something funked up'));
|
||||
});
|
||||
};
|
||||
|
||||
trans.sniff(function (err) {
|
||||
err.message.should.eql('something funked up');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('passed back the full server response', function (done) {
|
||||
trans.sniff(function (err, resp, status) {
|
||||
resp.should.include({
|
||||
ok: true,
|
||||
cluster_name: 'clustername'
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('passed back the server response code', function (done) {
|
||||
trans.sniff(function (err, resp, status) {
|
||||
status.should.eql(200);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user