Updated test
This commit is contained in:
@ -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",
|
||||
|
||||
190
test/behavior/resurrect.test.js
Normal file
190
test/behavior/resurrect.test.js
Normal file
@ -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()
|
||||
})
|
||||
})
|
||||
})
|
||||
@ -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) => {})
|
||||
|
||||
@ -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'))
|
||||
})
|
||||
|
||||
@ -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()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user