From 40cb37b2e81035613fe82d8ee92e31f96a6ccd24 Mon Sep 17 00:00:00 2001 From: delvedor Date: Mon, 5 Nov 2018 19:22:36 +0100 Subject: [PATCH] Updated test --- test/integration/test-runner.js | 42 ++++- test/unit/api.test.js | 167 +++++++++++++++++++ test/unit/connection-pool.test.js | 120 ++++++++++++-- test/unit/connection.test.js | 186 +++++++++++++++++---- test/unit/selectors.test.js | 9 +- test/unit/transport.test.js | 266 +++++++++++++++++++----------- 6 files changed, 638 insertions(+), 152 deletions(-) create mode 100644 test/unit/api.test.js diff --git a/test/integration/test-runner.js b/test/integration/test-runner.js index 1ee0f5260..228eadf35 100644 --- a/test/integration/test-runner.js +++ b/test/integration/test-runner.js @@ -246,14 +246,48 @@ TestRunner.prototype.set = function (key, name) { /** * Runs a client command - * TODO: handle `action.warning`, `action.catch`... * @param {object} the action to perform * @param {Queue} */ TestRunner.prototype.do = function (action, done) { const cmd = this.parseDo(action) const api = delve(this.client, cmd.method).bind(this.client) - api(cmd.params, (err, { body }) => { + api(cmd.params, (err, { body, warnings }) => { + if (action.warnings && warnings === null) { + this.tap.fail('We should get a warning header', action.warnings) + } else if (!action.warnings && warnings !== null) { + // if there is only the 'default shard will change' + // warning we skip the check, because the yaml + // spec may not be updated + let hasDefaultShardsWarning = false + warnings.forEach(h => { + if (/default\snumber\sof\sshards/g.test(h)) { + hasDefaultShardsWarning = true + } + }) + + if (hasDefaultShardsWarning === true && warnings.length > 1) { + this.tap.fail('We are not expecting warnings', warnings) + } + } else if (action.warnings && warnings !== null) { + // if the yaml warnings do not contain the + // 'default shard will change' warning + // we do not check it presence in the warnings array + // because the yaml spec may not be updated + let hasDefaultShardsWarning = false + action.warnings.forEach(h => { + if (/default\snumber\sof\sshards/g.test(h)) { + hasDefaultShardsWarning = true + } + }) + + if (hasDefaultShardsWarning === false) { + warnings = warnings.filter(h => !h.test(/default\snumber\sof\sshards/g)) + } + + this.tap.deepEqual(warnings, action.warnings) + } + if (action.catch) { this.tap.true( parseDoError(err, action.catch), @@ -269,10 +303,6 @@ TestRunner.prototype.do = function (action, done) { this.response = body } - if (action.warning) { - this.tap.todo('Handle warnings') - } - done() }) } diff --git a/test/unit/api.test.js b/test/unit/api.test.js new file mode 100644 index 000000000..ad095a585 --- /dev/null +++ b/test/unit/api.test.js @@ -0,0 +1,167 @@ +'use strict' + +const { test } = require('tap') +const { Client } = require('../../index') +const { buildServer } = require('../utils') + +test('Basic (callback)', t => { + t.plan(2) + + function handler (req, res) { + res.setHeader('Content-Type', 'application/json;utf=8') + res.end(JSON.stringify({ hello: 'world' })) + } + + buildServer(handler, ({ port }, server) => { + const client = new Client({ + host: `http://localhost:${port}` + }) + + client.search({ + index: 'test', + type: 'doc', + query: { + match: { foo: 'bar' } + } + }, (err, { body }) => { + t.error(err) + t.deepEqual(body, { hello: 'world' }) + }) + }) +}) + +test('Basic (promises)', t => { + t.plan(1) + + function handler (req, res) { + res.setHeader('Content-Type', 'application/json;utf=8') + res.end(JSON.stringify({ hello: 'world' })) + } + + buildServer(handler, ({ port }, server) => { + const client = new Client({ + host: `http://localhost:${port}` + }) + + client + .search({ + index: 'test', + type: 'doc', + query: { + match: { foo: 'bar' } + } + }) + .then(({ body }) => t.deepEqual(body, { hello: 'world' })) + .catch(t.fail) + }) +}) + +test('Error (callback)', t => { + t.plan(1) + + function handler (req, res) { + res.statusCode = 500 + res.setHeader('Content-Type', 'application/json;utf=8') + res.end(JSON.stringify({ hello: 'world' })) + } + + buildServer(handler, ({ port }, server) => { + const client = new Client({ + host: `http://localhost:${port}` + }) + + client.search({ + index: 'test', + type: 'doc', + query: { + match: { foo: 'bar' } + } + }, (err, { body }) => { + t.ok(err) + }) + }) +}) + +test('Error (promises)', t => { + t.plan(1) + + function handler (req, res) { + res.statusCode = 500 + res.setHeader('Content-Type', 'application/json;utf=8') + res.end(JSON.stringify({ hello: 'world' })) + } + + buildServer(handler, ({ port }, server) => { + const client = new Client({ + host: `http://localhost:${port}` + }) + + client + .search({ + index: 'test', + type: 'doc', + query: { + match: { foo: 'bar' } + } + }) + .then(t.fail) + .catch(err => t.ok(err)) + }) +}) + +test('Abort method (callback)', t => { + t.plan(3) + + function handler (req, res) { + res.setHeader('Content-Type', 'application/json;utf=8') + res.end(JSON.stringify({ hello: 'world' })) + } + + buildServer(handler, ({ port }, server) => { + const client = new Client({ + host: `http://localhost:${port}` + }) + + const request = client.search({ + index: 'test', + type: 'doc', + query: { + match: { foo: 'bar' } + } + }, (err, { body }) => { + t.error(err) + t.deepEqual(body, { hello: 'world' }) + }) + + t.type(request.abort, 'function') + }) +}) + +test('Abort is not supported in promises', t => { + t.plan(2) + + function handler (req, res) { + res.setHeader('Content-Type', 'application/json;utf=8') + res.end(JSON.stringify({ hello: 'world' })) + } + + buildServer(handler, ({ port }, server) => { + const client = new Client({ + host: `http://localhost:${port}` + }) + + const request = client.search({ + index: 'test', + type: 'doc', + query: { + match: { foo: 'bar' } + } + }) + + request + .then(({ body }) => t.deepEqual(body, { hello: 'world' })) + .catch(t.fail) + + t.type(request.abort, 'undefined') + }) +}) diff --git a/test/unit/connection-pool.test.js b/test/unit/connection-pool.test.js index 9bd300edf..f435fffd2 100644 --- a/test/unit/connection-pool.test.js +++ b/test/unit/connection-pool.test.js @@ -4,12 +4,11 @@ const { test } = require('tap') const { URL } = require('url') const ConnectionPool = require('../../lib/ConnectionPool') const Connection = require('../../lib/Connection') -const { RoundRobinSelector } = require('../../lib/Selectors') const { buildServer } = require('../utils') test('API', t => { t.test('addConnection', t => { - const pool = new ConnectionPool({ selector: new RoundRobinSelector() }) + const pool = new ConnectionPool() const href = 'http://localhost:9200/' pool.addConnection(href) t.ok(pool.connections.get(href) instanceof Connection) @@ -19,7 +18,7 @@ test('API', t => { }) t.test('addConnection should throw with two connections with the same id', t => { - const pool = new ConnectionPool({ selector: new RoundRobinSelector() }) + const pool = new ConnectionPool() const href = 'http://localhost:9200/' pool.addConnection(href) try { @@ -32,7 +31,7 @@ test('API', t => { }) t.test('markDead', t => { - const pool = new ConnectionPool({ selector: new RoundRobinSelector() }) + const pool = new ConnectionPool() const href = 'http://localhost:9200/' var connection = pool.addConnection(href) pool.markDead(connection) @@ -45,7 +44,7 @@ test('API', t => { }) t.test('markDead should sort the dead queue by deadTimeout', t => { - const pool = new ConnectionPool({ selector: new RoundRobinSelector() }) + const pool = new ConnectionPool() const href1 = 'http://localhost:9200/1' const href2 = 'http://localhost:9200/2' const conn1 = pool.addConnection(href1) @@ -59,7 +58,7 @@ test('API', t => { }) t.test('markAlive', t => { - const pool = new ConnectionPool({ selector: new RoundRobinSelector() }) + const pool = new ConnectionPool() const href = 'http://localhost:9200/' var connection = pool.addConnection(href) pool.markDead(connection) @@ -81,7 +80,6 @@ test('API', t => { buildServer(handler, ({ port }, server) => { const pool = new ConnectionPool({ - selector: new RoundRobinSelector(), resurrectStrategy: 'ping', pingTimeout: 3000 }) @@ -104,7 +102,6 @@ test('API', t => { buildServer(() => {}, ({ port }, server) => { server.close() const pool = new ConnectionPool({ - selector: new RoundRobinSelector(), resurrectStrategy: 'ping', pingTimeout: 3000 }) @@ -128,7 +125,6 @@ test('API', t => { t.test('optimistic strategy', t => { const pool = new ConnectionPool({ - selector: new RoundRobinSelector(), resurrectStrategy: 'optimistic' }) const href = 'http://localhost:9200/' @@ -147,7 +143,6 @@ test('API', t => { t.test('none strategy', t => { const pool = new ConnectionPool({ - selector: new RoundRobinSelector(), resurrectStrategy: 'none' }) const href = 'http://localhost:9200/' @@ -169,15 +164,104 @@ test('API', t => { }) t.test('getConnection', t => { - const pool = new ConnectionPool({ selector: new RoundRobinSelector() }) - const href = 'http://localhost:9200/' - pool.addConnection(href) - t.ok(pool.getConnection() instanceof Connection) + t.test('Should return a connection', t => { + const pool = new ConnectionPool() + const href = 'http://localhost:9200/' + pool.addConnection(href) + t.ok(pool.getConnection() instanceof Connection) + t.end() + }) + + t.test('filter option', t => { + const pool = new ConnectionPool() + const href1 = 'http://localhost:9200/' + const href2 = 'http://localhost:9200/other' + pool.addConnection([href1, href2]) + + const filter = node => node.id === href1 + t.strictEqual(pool.getConnection({ filter }).id, href1) + t.end() + }) + + t.test('weighter option', t => { + const pool = new ConnectionPool() + const href1 = 'http://localhost:9200/' + const href2 = 'http://localhost:9200/other' + pool.addConnection([href1, href2]) + + const weighter = node => node.id === href1 + t.strictEqual(pool.getConnection({ weighter }).id, href2) + t.end() + }) + + t.test('filter should be run before the weighter', t => { + const pool = new ConnectionPool() + const href1 = 'http://localhost:9200/' + const href2 = 'http://localhost:9200/other' + pool.addConnection([href1, href2]) + + const filter = node => node.id === href1 + const weighter = node => node.id !== href2 + t.strictEqual(pool.getConnection({ weighter, filter }).id, href1) + t.end() + }) + + t.test('filter and weighter should get Connection objects', t => { + t.plan(3) + const pool = new ConnectionPool() + const href1 = 'http://localhost:9200/' + const href2 = 'http://localhost:9200/other' + pool.addConnection([href1, href2]) + + const filter = node => { + t.ok(node instanceof Connection) + return true + } + const weighter = node => t.ok(node instanceof Connection) + pool.getConnection({ weighter, filter }) + }) + + t.test('filter and weighter should get alive connections', t => { + t.plan(3) + const pool = new ConnectionPool() + const href1 = 'http://localhost:9200/' + const href2 = 'http://localhost:9200/other' + const conn = pool.addConnection(href1) + pool.addConnection([href2, `${href2}/stuff`]) + pool.markDead(conn) + + const filter = node => { + t.strictEqual(node.status, Connection.statuses.ALIVE) + return true + } + const weighter = node => t.strictEqual(node.status, Connection.statuses.ALIVE) + pool.getConnection({ weighter, filter }) + }) + + t.test('filter and weighter as ConnectionPool option', t => { + t.plan(3) + + const href1 = 'http://localhost:9200/' + const href2 = 'http://localhost:9200/other' + const pool = new ConnectionPool({ + nodeFilter: node => { + t.ok('called') + return node.id === href1 + }, + nodeWeighter: node => { + t.ok('called') + return node.id !== href2 + } + }) + pool.addConnection([href1, href2]) + t.strictEqual(pool.getConnection().id, href1) + }) + t.end() }) t.test('removeConnection', t => { - const pool = new ConnectionPool({ selector: new RoundRobinSelector() }) + const pool = new ConnectionPool() const href = 'http://localhost:9200/' var connection = pool.addConnection(href) t.ok(pool.getConnection() instanceof Connection) @@ -187,7 +271,7 @@ test('API', t => { }) t.test('empty', t => { - const pool = new ConnectionPool({ selector: new RoundRobinSelector() }) + const pool = new ConnectionPool() pool.addConnection('http://localhost:9200/') pool.addConnection('http://localhost:9201/') pool.empty() @@ -198,7 +282,7 @@ test('API', t => { }) t.test('urlToHost', t => { - const pool = new ConnectionPool({ selector: new RoundRobinSelector() }) + const pool = new ConnectionPool() const url = 'http://localhost:9200' t.deepEqual( pool.urlToHost(url), @@ -208,7 +292,7 @@ test('API', t => { }) t.test('nodesToHost', t => { - const pool = new ConnectionPool({ selector: new RoundRobinSelector() }) + const pool = new ConnectionPool() const nodes = { a1: { http: { diff --git a/test/unit/connection.test.js b/test/unit/connection.test.js index f08a1b2fe..67c752576 100644 --- a/test/unit/connection.test.js +++ b/test/unit/connection.test.js @@ -1,8 +1,12 @@ 'use strict' const { test } = require('tap') +const { createGzip, createDeflate } = require('zlib') +const { URL } = require('url') +const intoStream = require('into-stream') const { buildServer } = require('../utils') const Connection = require('../../lib/Connection') +const { TimeoutError } = require('../../lib/errors') test('Basic (http)', t => { t.plan(4) @@ -17,10 +21,7 @@ test('Basic (http)', t => { buildServer(handler, ({ port }, server) => { const connection = new Connection({ - host: { - href: `http://localhost:${port}`, - protocol: 'http:' - } + host: new URL(`http://localhost:${port}`) }) connection.request({ path: '/hello', @@ -59,10 +60,7 @@ test('Basic (https)', t => { buildServer(handler, { secure: true }, ({ port }, server) => { const connection = new Connection({ - host: { - href: `https://localhost:${port}`, - protocol: 'https:' - } + host: new URL(`https://localhost:${port}`) }) connection.request({ path: '/hello', @@ -101,10 +99,7 @@ test('Basic (https with ssl agent)', t => { buildServer(handler, { secure: true }, ({ port, key, cert }, server) => { const connection = new Connection({ - host: { - href: `https://localhost:${port}`, - protocol: 'https:' - }, + host: new URL(`https://localhost:${port}`), ssl: { key, cert } }) connection.request({ @@ -144,10 +139,7 @@ test('Disable keep alive', t => { buildServer(handler, ({ port }, server) => { const connection = new Connection({ - host: { - href: `http://localhost:${port}`, - protocol: 'http:' - }, + host: new URL(`http://localhost:${port}`), agent: { keepAlive: false } }) connection.request({ @@ -178,17 +170,14 @@ test('Timeout support', t => { buildServer(handler, ({ port }, server) => { const connection = new Connection({ - host: { - href: `http://localhost:${port}`, - protocol: 'http:' - } + host: new URL(`http://localhost:${port}`) }) connection.request({ path: '/hello', method: 'GET', timeout: 500 }, (err, res) => { - t.ok(err.message, 'Request timed out') + t.ok(err instanceof TimeoutError) }) }) }) @@ -204,10 +193,7 @@ test('querystring', t => { buildServer(handler, ({ port }, server) => { const connection = new Connection({ - host: { - href: `http://localhost:${port}`, - protocol: 'http:' - } + host: new URL(`http://localhost:${port}`) }) connection.request({ path: '/hello', @@ -229,10 +215,7 @@ test('querystring', t => { buildServer(handler, ({ port }, server) => { const connection = new Connection({ - host: { - href: `http://localhost:${port}`, - protocol: 'http:' - } + host: new URL(`http://localhost:${port}`) }) connection.request({ path: '/hello', @@ -246,3 +229,148 @@ test('querystring', t => { t.end() }) + +test('Body request', t => { + t.plan(2) + + function handler (req, res) { + var payload = '' + req.setEncoding('utf8') + req.on('data', chunk => { payload += chunk }) + req.on('error', err => t.fail(err)) + req.on('end', () => { + t.strictEqual(payload, 'hello') + res.end('ok') + }) + } + + buildServer(handler, ({ port }, server) => { + const connection = new Connection({ + host: new URL(`http://localhost:${port}`) + }) + connection.request({ + path: '/hello', + method: 'POST', + body: 'hello' + }, (err, res) => { + t.error(err) + }) + }) +}) + +test('Should handle compression', t => { + t.test('gzip', t => { + t.plan(3) + + function handler (req, res) { + res.writeHead(200, { + 'Content-Type': 'application/json;utf=8', + 'Content-Encoding': 'gzip' + }) + intoStream(JSON.stringify({ hello: 'world' })) + .pipe(createGzip()) + .pipe(res) + } + + buildServer(handler, ({ port }, server) => { + const connection = new Connection({ + host: new URL(`http://localhost:${port}`) + }) + connection.request({ + path: '/hello', + method: 'GET' + }, (err, res) => { + t.error(err) + + t.match(res.headers, { + 'content-type': 'application/json;utf=8', + 'content-encoding': 'gzip' + }) + + var payload = '' + res.setEncoding('utf8') + res.on('data', chunk => { payload += chunk }) + res.on('error', err => t.fail(err)) + res.on('end', () => { + t.deepEqual(JSON.parse(payload), { hello: 'world' }) + }) + }) + }) + }) + + t.test('deflate', t => { + t.plan(3) + + function handler (req, res) { + res.writeHead(200, { + 'Content-Type': 'application/json;utf=8', + 'Content-Encoding': 'deflate' + }) + intoStream(JSON.stringify({ hello: 'world' })) + .pipe(createDeflate()) + .pipe(res) + } + + buildServer(handler, ({ port }, server) => { + const connection = new Connection({ + host: new URL(`http://localhost:${port}`) + }) + connection.request({ + path: '/hello', + method: 'GET' + }, (err, res) => { + t.error(err) + + t.match(res.headers, { + 'content-type': 'application/json;utf=8', + 'content-encoding': 'deflate' + }) + + var payload = '' + res.setEncoding('utf8') + res.on('data', chunk => { payload += chunk }) + res.on('error', err => t.fail(err)) + res.on('end', () => { + t.deepEqual(JSON.parse(payload), { hello: 'world' }) + }) + }) + }) + }) + + t.end() +}) + +test('Should not close a connection if there are open requests', t => { + t.plan(4) + + function handler (req, res) { + setTimeout(() => res.end('ok'), 1000) + } + + buildServer(handler, ({ port }, server) => { + const connection = new Connection({ + host: new URL(`http://localhost:${port}`) + }) + + setTimeout(() => { + t.strictEqual(connection._openRequests, 1) + connection.close() + }, 500) + + connection.request({ + path: '/hello', + method: 'GET' + }, (err, res) => { + t.error(err) + t.strictEqual(connection._openRequests, 0) + + var payload = '' + res.setEncoding('utf8') + res.on('data', chunk => { payload += chunk }) + res.on('error', err => t.fail(err)) + res.on('end', () => { + t.strictEqual(payload, 'ok') + }) + }) + }) +}) diff --git a/test/unit/selectors.test.js b/test/unit/selectors.test.js index 2f1f18502..4ce57b581 100644 --- a/test/unit/selectors.test.js +++ b/test/unit/selectors.test.js @@ -1,16 +1,16 @@ 'use strict' const { test } = require('tap') -const { RoundRobinSelector, RandomSelector } = require('../../lib/Selectors') +const { roundRobinSelector, randomSelector } = require('../../lib/ConnectionPool').internals test('RoundRobinSelector', t => { - const s = new RoundRobinSelector() + const selector = roundRobinSelector() const arr = [0, 1, 2, 3, 4, 5] t.plan(arr.length + 1) for (var i = 0; i <= arr.length; i++) { t.strictEqual( - s.select(arr), + selector(arr), i === arr.length ? arr[0] : arr[i] ) } @@ -18,7 +18,6 @@ test('RoundRobinSelector', t => { test('RandomSelector', t => { t.plan(1) - const s = new RandomSelector() const arr = [0, 1, 2, 3, 4, 5] - t.type(s.select(arr), 'number') + t.type(randomSelector(arr), 'number') }) diff --git a/test/unit/transport.test.js b/test/unit/transport.test.js index 3acc9e8ba..e0464456c 100644 --- a/test/unit/transport.test.js +++ b/test/unit/transport.test.js @@ -15,7 +15,6 @@ const { const ConnectionPool = require('../../lib/ConnectionPool') const Serializer = require('../../lib/Serializer') const Transport = require('../../lib/Transport') -const { RoundRobinSelector } = require('../../lib/Selectors') test('Basic', t => { t.plan(2) @@ -25,9 +24,7 @@ test('Basic', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -69,9 +66,7 @@ test('Send POST', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -126,9 +121,7 @@ test('Send POST (ndjson)', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -160,9 +153,7 @@ test('Not JSON payload from server', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -187,9 +178,7 @@ test('Not JSON payload from server', t => { test('NoLivingConnectionsError', t => { t.plan(1) - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() const transport = new Transport({ emit: () => {}, @@ -211,9 +200,7 @@ test('NoLivingConnectionsError', t => { test('SerializationError', t => { t.plan(1) - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection('http://localhost:9200') const transport = new Transport({ @@ -245,9 +232,7 @@ test('DeserializationError', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -287,9 +272,7 @@ test('TimeoutError (should call markDead on the failing connection)', t => { } buildServer(handler, ({ port }, server) => { - const pool = new CustomConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new CustomConnectionPool() pool.addConnection({ host: new URL(`http://localhost:${port}`), id: 'node1' @@ -326,9 +309,7 @@ test('ConnectionError (should call markDead on the failing connection)', t => { buildServer(() => {}, ({ port }, server) => { server.close() - const pool = new CustomConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new CustomConnectionPool() pool.addConnection({ host: new URL(`http://localhost:${port}`), id: 'node1' @@ -370,9 +351,7 @@ test('Retry mechanism', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection([{ host: new URL(`http://localhost:${port}`), id: 'node1' @@ -420,9 +399,7 @@ test('Should call markAlive with a successful response', t => { } buildServer(handler, ({ port }, server) => { - const pool = new CustomConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new CustomConnectionPool() pool.addConnection({ host: new URL(`http://localhost:${port}`), id: 'node1' @@ -463,9 +440,7 @@ test('Should call resurrect on every request', t => { } buildServer(handler, ({ port }, server) => { - const pool = new CustomConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new CustomConnectionPool() pool.addConnection({ host: new URL(`http://localhost:${port}`), id: 'node1' @@ -502,9 +477,7 @@ test('Should return a request aborter utility', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection({ host: new URL(`http://localhost:${port}`), id: 'node1' @@ -542,9 +515,7 @@ test('ResponseError', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -578,9 +549,7 @@ test('Override requestTimeout', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -635,9 +604,7 @@ test('sniff', t => { } buildServer(handler, ({ port }, server) => { - const pool = new CustomConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new CustomConnectionPool() pool.addConnection(`http://localhost:${port}`) // eslint-disable-next-line @@ -688,9 +655,7 @@ test('sniff', t => { } buildServer(handler, ({ port }, server) => { - const pool = new CustomConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new CustomConnectionPool() pool.addConnection(`http://localhost:${port}`) pool.addConnection(`http://localhost:${port}/other`) @@ -742,9 +707,7 @@ test('sniff', t => { } buildServer(handler, ({ port }, server) => { - const pool = new CustomConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new CustomConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -783,9 +746,7 @@ test('sniff', t => { buildServer(() => {}, ({ port }, server) => { server.close() - const pool = new CustomConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new CustomConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -828,9 +789,7 @@ test(`Should mark as dead connections where the statusCode is 502/3/4 } buildServer(handler, ({ port }, server) => { - const pool = new CustomConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new CustomConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -885,9 +844,7 @@ test('Should retry the request if the statusCode is 502/3/4', t => { } buildServer(handler, ({ port }, server) => { - const pool = new CustomConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new CustomConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -923,9 +880,7 @@ test('Ignore status code', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -973,9 +928,7 @@ test('Should serialize the querystring', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -1014,9 +967,7 @@ test('timeout option', t => { t.plan(1) buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection({ host: new URL(`http://localhost:${port}`), id: 'node1' @@ -1045,9 +996,7 @@ test('timeout option', t => { t.plan(1) buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection({ host: new URL(`http://localhost:${port}`), id: 'node1' @@ -1081,9 +1030,7 @@ test('timeout option', t => { t.plan(1) buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection({ host: new URL(`http://localhost:${port}`), id: 'node1' @@ -1112,9 +1059,7 @@ test('timeout option', t => { t.plan(1) buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection({ host: new URL(`http://localhost:${port}`), id: 'node1' @@ -1155,9 +1100,7 @@ test('Should cast to boolean HEAD request', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -1189,9 +1132,7 @@ test('Should cast to boolean HEAD request', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -1223,9 +1164,7 @@ test('Should cast to boolean HEAD request', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -1256,9 +1195,7 @@ test('Should cast to boolean HEAD request', t => { } buildServer(handler, ({ port }, server) => { - const pool = new ConnectionPool({ - selector: new RoundRobinSelector() - }) + const pool = new ConnectionPool() pool.addConnection(`http://localhost:${port}`) const transport = new Transport({ @@ -1282,3 +1219,144 @@ test('Should cast to boolean HEAD request', t => { t.end() }) + +test('Suggest compression', t => { + t.plan(2) + function handler (req, res) { + t.match(req.headers, { + 'accept-encoding': 'gzip,deflate' + }) + res.setHeader('Content-Type', 'application/json;utf=8') + res.end(JSON.stringify({ hello: 'world' })) + } + + buildServer(handler, ({ port }, server) => { + const pool = new ConnectionPool() + pool.addConnection(`http://localhost:${port}`) + + const transport = new Transport({ + emit: () => {}, + connectionPool: pool, + serializer: new Serializer(), + maxRetries: 3, + requestTimeout: 30000, + sniffInterval: false, + sniffOnStart: false, + suggestCompression: true + }) + + transport.request({ + method: 'GET', + path: '/hello' + }, (err, { body }) => { + t.error(err) + }) + }) +}) + +test('Warning header', t => { + t.test('Single warning', t => { + t.plan(3) + + const warn = '112 - "cache down" "Wed, 21 Oct 2015 07:28:00 GMT"' + function handler (req, res) { + res.setHeader('Content-Type', 'application/json;utf=8') + res.setHeader('Warning', warn) + res.end(JSON.stringify({ hello: 'world' })) + } + + buildServer(handler, ({ port }, server) => { + const pool = new ConnectionPool() + pool.addConnection(`http://localhost:${port}`) + + const transport = new Transport({ + emit: () => {}, + connectionPool: pool, + serializer: new Serializer(), + maxRetries: 3, + requestTimeout: 30000, + sniffInterval: false, + sniffOnStart: false + }) + + transport.request({ + method: 'GET', + path: '/hello' + }, (err, { warnings }) => { + t.error(err) + t.deepEqual(warnings, [warn]) + warnings.forEach(w => t.type(w, 'string')) + }) + }) + }) + + t.test('Multiple warnings', t => { + t.plan(4) + + const warn1 = '112 - "cache down" "Wed, 21 Oct 2015 07:28:00 GMT"' + const warn2 = '199 agent "Error message" "2015-01-01"' + function handler (req, res) { + res.setHeader('Content-Type', 'application/json;utf=8') + res.setHeader('Warning', warn1 + ',' + warn2) + res.end(JSON.stringify({ hello: 'world' })) + } + + buildServer(handler, ({ port }, server) => { + const pool = new ConnectionPool() + pool.addConnection(`http://localhost:${port}`) + + const transport = new Transport({ + emit: () => {}, + connectionPool: pool, + serializer: new Serializer(), + maxRetries: 3, + requestTimeout: 30000, + sniffInterval: false, + sniffOnStart: false + }) + + transport.request({ + method: 'GET', + path: '/hello' + }, (err, { warnings }) => { + t.error(err) + t.deepEqual(warnings, [warn1, warn2]) + warnings.forEach(w => t.type(w, 'string')) + }) + }) + }) + + t.test('No warnings', t => { + t.plan(2) + + function handler (req, res) { + res.setHeader('Content-Type', 'application/json;utf=8') + res.end(JSON.stringify({ hello: 'world' })) + } + + buildServer(handler, ({ port }, server) => { + const pool = new ConnectionPool() + pool.addConnection(`http://localhost:${port}`) + + const transport = new Transport({ + emit: () => {}, + connectionPool: pool, + serializer: new Serializer(), + maxRetries: 3, + requestTimeout: 30000, + sniffInterval: false, + sniffOnStart: false + }) + + transport.request({ + method: 'GET', + path: '/hello' + }, (err, { warnings }) => { + t.error(err) + t.strictEqual(warnings, null) + }) + }) + }) + + t.end() +})