Summary of Changes:

- Polished some Grunt config options while testing livereload capabilities in grunt-watch
- tests for connection_pool selection with no living connections
- tests for connection abstract's mini request implementation for ping.
This commit is contained in:
Spencer Alger
2013-12-18 17:11:32 -07:00
parent 3057c25c26
commit 50be1e86b3
8 changed files with 131 additions and 28 deletions

View File

@ -5,23 +5,15 @@ module.exports = {
options: { options: {
require: ['should'] require: ['should']
}, },
coverage: {
src: unitTests,
options: {
reporter: 'mocha-lcov-reporter',
coveralls: {
serviceName: 'travis-ci',
repoToken: process.env.ESJS_COVERALS_REPO_TOKEN
}
}
},
unit: { unit: {
src: unitTests src: unitTests
}, },
integration: { integration: {
src: integrationTests src: integrationTests
}, },
make_html_unit_cov: {
// run the unit tests, and update coverage.html
make_coverage_html: {
src: unitTests, src: unitTests,
options: { options: {
reporter: 'html-cov', reporter: 'html-cov',
@ -29,4 +21,14 @@ module.exports = {
} }
}, },
// for use by travis
ship_coverage: {
src: unitTests,
options: {
reporter: 'mocha-lcov-reporter',
coveralls: {
serviceName: 'travis-ci'
}
}
}
}; };

View File

@ -1,5 +1,5 @@
module.exports = { module.exports = {
html_unit_cov: { coverage: {
path: 'coverage.html', path: 'coverage.html',
app: 'Google Chrome' app: 'Google Chrome'
} }

View File

@ -2,16 +2,16 @@ module.exports = {
source: { source: {
files: [ files: [
'src/**/*.js', 'src/**/*.js',
'test/unit/**/*.js',
'grunt/**/*.js', 'grunt/**/*.js',
'test/unit/**/*.js',
'Gruntfile.js' 'Gruntfile.js'
], ],
tasks: [ tasks: [
'jshint', 'jshint',
'run:unit_tests' 'mochacov:unit'
], ],
options: { options: {
interrupt: true, interrupt: true
} }
} }
}; };

View File

@ -2,7 +2,6 @@ module.exports = function (grunt) {
// Default task runs the build process. // Default task runs the build process.
grunt.registerTask('default', [ grunt.registerTask('default', [
'generate',
'test' 'test'
]); ]);
@ -13,17 +12,17 @@ module.exports = function (grunt) {
grunt.registerTask('test', [ grunt.registerTask('test', [
'jshint', 'jshint',
'mochacov:unit', 'mochacov:unit',
'run:generate', 'generate',
'mochacov:integration', 'mochacov:integration',
]); ]);
grunt.registerTask('coverage', [ grunt.registerTask('coverage', [
'mochacov:make_html_unit_cov', 'mochacov:make_coverage_html',
'open:html_unit_cov' 'open:coverage'
]); ]);
grunt.registerTask('travis', [ grunt.registerTask('travis', [
'test', 'test',
'mochacov:coverage' 'mochacov:ship_coverage'
]); ]);
}; };

View File

@ -59,7 +59,6 @@
}, },
"scripts": { "scripts": {
"test": "grunt test", "test": "grunt test",
"coverage": "mocha test/unit/test_*.js --require blanket -R html-cov > coverage.html && open -a \"Google Chrome\" ./coverage.html",
"blanket": { "blanket": {
"pattern": "src" "pattern": "src"
} }

View File

@ -17,6 +17,12 @@ describe('Client instances creation', function () {
}).should.throw(/previous "elasticsearch" module/); }).should.throw(/previous "elasticsearch" module/);
}); });
it('Succeeds even not called with new', function () {
var client = es.Client();
client.bulk.should.eql(api.bulk);
client.cluster.nodeStats.should.eql(api.cluster.prototype.nodeStats);
});
it('inherits the api', function () { it('inherits the api', function () {
client.bulk.should.eql(api.bulk); client.bulk.should.eql(api.bulk);
client.cluster.nodeStats.should.eql(api.cluster.prototype.nodeStats); client.cluster.nodeStats.should.eql(api.cluster.prototype.nodeStats);

View File

@ -1,7 +1,9 @@
var ConnectionAbstract = require('../../src/lib/connection'); var ConnectionAbstract = require('../../src/lib/connection');
var Host = require('../../src/lib/host'); var Host = require('../../src/lib/host');
var sinon = require('sinon'); var sinon = require('sinon');
var should = require('should');
var _ = require('lodash'); var _ = require('lodash');
var errors = require('../../src/lib/errors');
var stub = require('./auto_release_stub').make(); var stub = require('./auto_release_stub').make();
@ -72,8 +74,62 @@ describe('Connection Abstract', function () {
conn.request.callCount.should.eql(1); conn.request.callCount.should.eql(1);
}); });
it('sets a timer for the request'); it('sets a timer for the request', function (done) {
it('aborts the request if it takes too long'); var conn = new ConnectionAbstract(host);
var clock = sinon.useFakeTimers('setTimeout', 'clearTimeout');
var order = 0;
stub(conn, 'request', function (params, cb) {
setTimeout(function () {
should(++order).eql(2);
cb();
}, 10001);
});
conn.ping({
requestTimeout: 100
}, function (err) {
should(++order).eql(1);
err.should.be.an.instanceOf(errors.RequestTimeout);
});
process.nextTick(function () {
clock.tick(1000);
clock.tick(10000);
clock.restore();
done();
});
});
it('calls the requestAborter if req takes too long', function (done) {
var conn = new ConnectionAbstract(host);
var clock = sinon.useFakeTimers('setTimeout', 'clearTimeout');
var order = 0;
stub(conn, 'request', function (params, cb) {
setTimeout(function () {
should(++order).eql(3);
cb();
}, 10001);
return function () {
should(++order).eql(1);
};
});
conn.ping({
requestTimeout: 100
}, function (err) {
should(++order).eql(2);
err.should.be.an.instanceOf(errors.RequestTimeout);
});
process.nextTick(function () {
clock.tick(1000);
clock.tick(10000);
clock.restore();
done();
});
});
it('ignores the response from the request if it already aborted'); it('ignores the response from the request if it already aborted');
}); });

View File

@ -1,10 +1,12 @@
var ConnectionPool = require('../../src/lib/connection_pool'); var ConnectionPool = require('../../src/lib/connection_pool');
var Host = require('../../src/lib/host'); var Host = require('../../src/lib/host');
var errors = require('../../src/lib/errors');
var ConnectionAbstract = require('../../src/lib/connection'); var ConnectionAbstract = require('../../src/lib/connection');
var _ = require('lodash'); var _ = require('lodash');
var EventEmitter = require('events').EventEmitter; var EventEmitter = require('events').EventEmitter;
var should = require('should'); var should = require('should');
var sinon = require('sinon'); var sinon = require('sinon');
var stub = require('./auto_release_stub').make();
function listenerCount(emitter, event) { function listenerCount(emitter, event) {
if (EventEmitter.listenerCount) { if (EventEmitter.listenerCount) {
@ -157,14 +159,53 @@ describe('Connection Pool', function () {
}); });
}); });
it('should automatically select the dead connection with the shortest timeout when there no living connections', });
describe('Connection selection with no living nodes', function () {
it('should ping all of the dead nodes, in order of oldest timeout, and return the first that\'s okay',
function (done) { function (done) {
pool.setHosts([]); var clock = sinon.useFakeTimers('setTimeout', 'clearTimeout');
pool._conns.alive = []; var pool = new ConnectionPool({
pool._conns.dead = [1, 2, 3]; deadTimeout: 10000
});
var connections = [
new ConnectionAbstract(new Host('http://localhost:9200')),
new ConnectionAbstract(new Host('http://localhost:9201')),
new ConnectionAbstract(new Host('http://localhost:9202')),
new ConnectionAbstract(new Host('http://localhost:9203'))
];
var pingQueue = _.shuffle(connections);
var expectedSelection = pingQueue[pingQueue.length - 1];
pingQueue.forEach(function (conn) {
pool.addConnection(conn);
stub(conn, 'ping', function (params, cb) {
if (typeof params === 'function') {
cb = params;
}
var expectedConn = pingQueue.shift();
conn.should.be.exactly(expectedConn);
if (pingQueue.length) {
process.nextTick(function () {
cb(new Error('keep trying'));
});
} else {
process.nextTick(function () {
cb(null, true);
});
}
});
conn.setStatus('dead');
clock.tick(500);
});
pool.select(function (err, selection) { pool.select(function (err, selection) {
// selection.should.be.exactly(1); clock.restore();
selection.should.be.exactly(expectedSelection);
pingQueue.should.have.length(0);
pool.setHosts([]);
should.not.exist(err);
done(); done();
}); });
}); });