From 230b08ab8697ba15ee36009f4011c662d5c02879 Mon Sep 17 00:00:00 2001 From: delvedor Date: Mon, 10 Dec 2018 20:14:51 +0100 Subject: [PATCH] Updated test --- package.json | 1 + test/behavior/resurrect.test.js | 190 ++++++++++++++++++++++++++++++++ test/types/index.ts | 2 + test/unit/client.test.js | 64 ++++++++++- test/utils/buildCluster.js | 16 +-- 5 files changed, 264 insertions(+), 9 deletions(-) create mode 100644 test/behavior/resurrect.test.js diff --git a/package.json b/package.json index a19bbf75b..992edb292 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "deepmerge": "^2.2.1", "into-stream": "^4.0.0", "js-yaml": "^3.12.0", + "lolex": "^3.0.0", "minimist": "^1.2.0", "ora": "^3.0.0", "rimraf": "^2.6.2", diff --git a/test/behavior/resurrect.test.js b/test/behavior/resurrect.test.js new file mode 100644 index 000000000..2a1c412d0 --- /dev/null +++ b/test/behavior/resurrect.test.js @@ -0,0 +1,190 @@ +'use strict' + +const { test } = require('tap') +const { URL } = require('url') +const lolex = require('lolex') +const workq = require('workq') +const { buildCluster } = require('../utils') +const { Client, events } = require('../../index') + +/** + * The aim of this test is to verify how the resurrect logic behaves + * in a multi node situation. + * The `buildCluster` utility can boot an arbitrary number + * of nodes, that you can kill or spawn at your will. + * The resurrect API can be tested with its callback + * or by using the `resurrect` event (to handle automatically + * triggered resurrections). + */ + +test('Should execute the recurrect API with the ping strategy', t => { + t.plan(6) + + const clock = lolex.install({ toFake: ['Date'] }) + const q = workq() + + buildCluster({ numberOfNodes: 2 }, cluster => { + const client = new Client({ + nodes: [{ + url: new URL(cluster.nodes[Object.keys(cluster.nodes)[0]].url), + id: 'node0' + }, { + url: new URL(cluster.nodes[Object.keys(cluster.nodes)[1]].url), + id: 'node1' + }], + maxRetries: 0 + }) + + client.on(events.RESURRECT, (err, meta) => { + t.error(err) + t.strictEqual(meta.strategy, 'ping') + t.false(meta.isAlive) + t.strictEqual(meta.connection.id, 'node0') + }) + + q.add((q, done) => { + cluster.kill('node0') + setTimeout(done, 100) + }) + + q.add((q, done) => { + client.info((err, result) => { + t.ok(err) + done() + }) + }) + + q.add((q, done) => { + clock.tick(10) + client.info((err, result) => { + t.error(err) + done() + }) + }) + + t.teardown(() => { + clock.uninstall() + cluster.shutdown() + }) + }) +}) + +test('Resurrect a node and handle 502/3/4 status code', t => { + t.plan(11) + + const clock = lolex.install({ toFake: ['Date'] }) + const q = workq() + + var count = 0 + function handler (req, res) { + res.statusCode = count < 2 ? 502 : 200 + res.setHeader('content-type', 'application/json') + res.end(JSON.stringify({ hello: 'world' })) + count++ + } + + buildCluster({ handler, numberOfNodes: 2 }, ({ nodes, shutdown }) => { + const client = new Client({ + nodes: [{ + url: new URL(nodes[Object.keys(nodes)[0]].url), + id: 'node0' + }, { + url: new URL(nodes[Object.keys(nodes)[1]].url), + id: 'node1' + }], + maxRetries: 0 + }) + + client.on(events.RESURRECT, (err, meta) => { + t.error(err) + t.strictEqual(meta.strategy, 'ping') + t.strictEqual(meta.connection.id, 'node0') + if (count < 3) { + t.false(meta.isAlive) + } else { + t.true(meta.isAlive) + } + }) + + q.add((q, done) => { + client.info((err, result) => { + t.ok(err) + done() + }) + }) + + q.add((q, done) => { + clock.tick(10) + client.info((err, result) => { + t.error(err) + done() + }) + }) + + q.add((q, done) => { + clock.tick(150000) + client.info((err, result) => { + t.error(err) + done() + }) + }) + + t.teardown(() => { + clock.uninstall() + shutdown() + }) + }) +}) + +test('Should execute the recurrect API with the optimistic strategy', t => { + t.plan(6) + + const clock = lolex.install({ toFake: ['Date'] }) + const q = workq() + + buildCluster({ numberOfNodes: 2 }, cluster => { + const client = new Client({ + nodes: [{ + url: new URL(cluster.nodes[Object.keys(cluster.nodes)[0]].url), + id: 'node0' + }, { + url: new URL(cluster.nodes[Object.keys(cluster.nodes)[1]].url), + id: 'node1' + }], + maxRetries: 0, + resurrectStrategy: 'optimistic' + }) + + client.on(events.RESURRECT, (err, meta) => { + t.error(err) + t.strictEqual(meta.strategy, 'optimistic') + t.true(meta.isAlive) + t.strictEqual(meta.connection.id, 'node0') + }) + + q.add((q, done) => { + cluster.kill('node0') + setTimeout(done, 100) + }) + + q.add((q, done) => { + client.info((err, result) => { + t.ok(err) + done() + }) + }) + + q.add((q, done) => { + clock.tick(10) + client.info((err, result) => { + t.error(err) + done() + }) + }) + + t.teardown(() => { + clock.uninstall() + cluster.shutdown() + }) + }) +}) diff --git a/test/types/index.ts b/test/types/index.ts index e23aed952..30629eeb5 100644 --- a/test/types/index.ts +++ b/test/types/index.ts @@ -5,6 +5,7 @@ import { ApiResponse, EventMeta, SniffMeta, + ResurrectMeta, events } from '../../index' @@ -13,6 +14,7 @@ const client = new Client({ node: 'http://localhost:9200' }) client.on(events.REQUEST, (err: Error | null, meta: EventMeta) => {}) client.on(events.RESPONSE, (err: Error | null, meta: EventMeta) => {}) client.on(events.SNIFF, (err: Error | null, meta: SniffMeta) => {}) +client.on(events.RESURRECT, (err: Error | null, meta: ResurrectMeta) => {}) // Callbacks client.info((err: Error | null, result: ApiResponse) => {}) diff --git a/test/unit/client.test.js b/test/unit/client.test.js index 95a87ffb4..100669d0a 100644 --- a/test/unit/client.test.js +++ b/test/unit/client.test.js @@ -2,7 +2,8 @@ const { test } = require('tap') const { URL } = require('url') -const { Client } = require('../../index') +const { Client, ConnectionPool } = require('../../index') +const { buildServer } = require('../utils') test('Configure host', t => { t.test('Single string', t => { @@ -165,3 +166,64 @@ test('Configure host', t => { t.end() }) + +test('Node with auth data in the url', t => { + t.plan(3) + + function handler (req, res) { + t.match(req.headers, { + authorization: 'Basic Zm9vOmJhcg==' + }) + res.setHeader('Content-Type', 'application/json;utf=8') + res.end(JSON.stringify({ hello: 'world' })) + } + + buildServer(handler, ({ port }, server) => { + const client = new Client({ + node: `http://foo:bar@localhost:${port}` + }) + + client.info((err, { body }) => { + t.error(err) + t.deepEqual(body, { hello: 'world' }) + server.stop() + }) + }) +}) + +test('Client close', t => { + t.plan(2) + + class MyConnectionPool extends ConnectionPool { + empty () { + t.ok('called') + super.empty() + } + } + + const client = new Client({ + node: 'http://localhost:9200', + ConnectionPool: MyConnectionPool + }) + + client.close(() => t.pass('Closed')) +}) + +test('Client close (promise)', t => { + t.plan(2) + + class MyConnectionPool extends ConnectionPool { + empty () { + t.ok('called') + super.empty() + } + } + + const client = new Client({ + node: 'http://localhost:9200', + ConnectionPool: MyConnectionPool + }) + + client.close() + .then(() => t.pass('Closed')) +}) diff --git a/test/utils/buildCluster.js b/test/utils/buildCluster.js index 79b0658ed..13c208f9f 100644 --- a/test/utils/buildCluster.js +++ b/test/utils/buildCluster.js @@ -5,20 +5,20 @@ const workq = require('workq') const buildServer = require('./buildServer') var id = 0 -function buildCluster (opts, callback) { +function buildCluster (options, callback) { const clusterId = id++ debug(`Booting cluster '${clusterId}'`) - if (typeof opts === 'function') { - callback = opts - opts = {} + if (typeof options === 'function') { + callback = options + options = {} } const q = workq() const nodes = {} const sniffResult = { nodes: {} } - opts.numberOfNodes = opts.numberOfNodes || 4 - for (var i = 0; i < opts.numberOfNodes; i++) { + options.numberOfNodes = options.numberOfNodes || 4 + for (var i = 0; i < options.numberOfNodes; i++) { q.add(bootNode, { id: `node${i}` }) } @@ -32,7 +32,7 @@ function buildCluster (opts, callback) { } } - buildServer(handler, ({ port }, server) => { + buildServer(options.handler || handler, ({ port }, server) => { nodes[opts.id] = { url: `http://localhost:${port}`, server @@ -77,7 +77,7 @@ function buildCluster (opts, callback) { } q.drain(done => { - debug(`Cluster '${clusterId}' booted with ${opts.numberOfNodes} nodes`) + debug(`Cluster '${clusterId}' booted with ${options.numberOfNodes} nodes`) callback(cluster) done() })