@condor-labs/redis
Version:
This module provide and usefull helper to use the official Node_redis library.
321 lines (272 loc) • 13.6 kB
JavaScript
;
const logger = require('@condor-labs/logger');
const sinon = require('sinon');
const helper = require('./index');
const fs = require('fs');
const redis = require('redis');
const os = require("os")
const { assert, expect } = require('chai');
const invalidSettings = {
bar: 'foo'
};
const validSettings = {
socket: {
host: 'mhost',
port: 1234,
},
prefix: 'mprefix',
password: 'mpass',
clientName: 'test_service_api_0'
};
const ClienList = ['id=8104296001002 addr=186.99.6.38:58898 laddr=172.16.0.38:12726 fd=4501 name=test_service_api_0 age=3 idle=1 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=2147483647 obl=0 oll=0 omem=0 totMem=0 events=r cmd=CLIENT user=default redir=r\r',
'id=8104296001003 addr=186.99.6.38:58898 laddr=172.16.0.38:12726 fd=4501 name=test_service_api_0 age=1 idle=1 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=2147483647 obl=0 oll=0 omem=0 totMem=0 events=r cmd=CLIENT user=default redir=r\r']
const ClientInfo = 'id=8104296001002 addr=186.99.6.38:58898 laddr=172.16.0.38:12726 fd=4501 name=test_service_api_0 age=2 idle=1 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=2147483647 obl=0 oll=0 omem=0 totMem=0 events=r cmd=CLIENT user=default redir=r\r'
describe('REDIS TESTINGS', () => {
//helper._setSettings
describe('When _setSettings function is called', () => {
let _validateSettingsStub = {};
beforeEach(() => {
_validateSettingsStub = sinon.stub(helper, "_validateSettings");
});
afterEach(() => {
_validateSettingsStub.restore();
});
it('Should call the helper._validateSettings method once', () => {
_validateSettingsStub.returns(true);
helper._setSettings();
assert.equal(helper._validateSettings.calledOnce, true);
});
it('when the clientName is empty it Should set hostname as clientName', () => {
_validateSettingsStub.returns(true);
validSettings.clientName = null
helper._setSettings({ ...validSettings });
assert.equal(helper._settings.clientName.includes(os.hostname()), true);
});
it('when the clientName is not empty it Should set clientName as clientName', () => {
_validateSettingsStub.returns(true);
helper._setSettings(validSettings);
assert.equal(helper._settings.clientName.includes(validSettings.clientName), true);
});
it('Should throws an error when the settings are invalid and should not set the settings', () => {
try {
helper._settings = void 0
_validateSettingsStub.returns(false);
helper._setSettings(invalidSettings);
} catch (error) {
expect(error).to.be.instanceOf(Error);
expect(error.message).to.be.equal(helper._errorMsgInvalidSetting);
expect(helper._settings).to.be.equal(undefined);
}
});
it('Should set the settings when they are valid', () => {
_validateSettingsStub.returns(true);
helper._setSettings(validSettings);
expect(helper._settings).to.be.equal(validSettings);
});
});
//helper._validateSettings
describe('When _validateSettings function is called', () => {
let loggerErrorStub = {};
beforeEach(() => {
loggerErrorStub = sinon.stub(logger, "error").callsFake(() => { });
});
afterEach(() => {
loggerErrorStub.restore();
});
it('Should log the right error message when no settings are passed', () => {
helper._validateSettings();
expect(loggerErrorStub.calledOnce).to.be.true;
expect(loggerErrorStub.calledWith(helper._errorMsgUndefinedSetting)).to.be.true;
});
it('Should return false when no settings are passed', () => {
expect(helper._validateSettings()).to.be.equal(false);
});
it('Should log the right error message when settings passed have an invalid format', () => {
helper._validateSettings(invalidSettings);
expect(loggerErrorStub.calledOnce).to.be.true;
});
it('Should returns false when settings passed have an invalid format', () => {
const result = helper._validateSettings(invalidSettings);
expect(result).to.be.equal(false);
});
it('Should returns false when settings.ssl is true and not sslKeys paths are present', () => {
const settings = {
...validSettings,
ssl: true
}
const result = helper._validateSettings(settings);
expect(result).to.be.equal(false);
});
it('Should not log any error message when settings passed are valid', () => {
helper._validateSettings(validSettings);
expect(loggerErrorStub.calledOnce).to.be.equal(false);
});
it('Should return true when settings passed are valid', () => {
const result = helper._validateSettings(validSettings);
expect(result).to.be.equal(true);
});
});
describe('When getClient function is called', () => {
let _validateSettingstub = {};
let readFileSyncStub = {};
let createClientStub = {};
let _verifyUniqueConnection = {};
beforeEach(() => {
_validateSettingstub = sinon.stub(helper, "_validateSettings");
_verifyUniqueConnection = sinon.stub(helper, "_verifyUniqueConnection");
readFileSyncStub = sinon.stub(fs, "readFileSync").callsFake((param) => { return param });
createClientStub = sinon.stub(redis, "createClient").callsFake(() => ({
on: () => { },
connect: () => { },
sendCommand: () => { }
}));
});
afterEach(() => {
_validateSettingstub.restore();
readFileSyncStub.restore();
createClientStub.restore();
_verifyUniqueConnection.restore();
helper._client = void 0
});
it('Should return a valid client when it is already initialized', async () => {
helper._client = {}
const client = await helper.getClient();
expect(client).to.be.equal(helper._client);
helper._client = undefined;
});
it('Should calls validateSetting function once when the client has not been initialized', async () => {
_validateSettingstub.returns(true);
await helper.getClient();
expect(_validateSettingstub.calledOnce).to.be.true;
});
it('Should throws an error when the settings are invalid', async () => {
_validateSettingstub.returns(false);
try {
await helper.getClient();
} catch (error) {
expect(error.message).to.be.equal(helper._errorMsgInvalidSetting);
expect(error).to.be.instanceOf(Error);
}
});
it('Should set the tls object property to redisOptions object with the right properties when ssl property is configured to true', async () => {
_validateSettingstub.returns(true);
validSettings.socket.tls = true;
validSettings.socket.key = "sslKeyPath";
validSettings.socket.cert = "sslCertPath";
validSettings.socket.ca = "sslCaPath";
helper._setSettings(validSettings)
await helper.getClient();
expect(helper._settings.socket).to.have.property('tls');
expect(helper._settings.socket).to.have.property('key');
expect(helper._settings.socket).to.have.property('cert');
expect(helper._settings.socket).to.have.property('ca');
expect(helper._settings.socket.tls).to.be.equal(true);
expect(readFileSyncStub.callCount).to.be.equal(3);
expect(readFileSyncStub.getCalls()[0].args).be.deep.equal([validSettings.socket.key, { encoding: 'ascii' }]);
expect(readFileSyncStub.getCalls()[1].args).be.deep.equal([validSettings.socket.cert, { encoding: 'ascii' }]);
expect(readFileSyncStub.getCalls()[2].args).be.deep.equal([validSettings.socket.ca[0], { encoding: 'ascii' }]);
});
it('Should calls redis.createClient once with the right params', async () => {
_validateSettingstub.returns(true);
validSettings.socket.tls = false;
await helper.getClient();
expect(createClientStub.calledOnce).to.be.true;
expect(createClientStub.calledWith(helper._settings)).to.be.true;
});
it('Should calls _verifyUniqueConnection function once when the client has not been initialized', async () => {
_validateSettingstub.returns(true);
await helper.getClient();
expect(_verifyUniqueConnection.calledOnce).to.be.true;
});
});
describe('When _verifyUniqueConnection function is called', () => {
let _clientInfo = {};
let _killClient = {};
let _clientList = {};
beforeEach(() => {
_clientInfo = sinon.stub(helper, "_clientInfo").returns(ClientInfo);
_clientList = sinon.stub(helper, "_clientList").returns(ClienList);
_killClient = sinon.stub(helper, "_killClient").returns();
});
afterEach(() => {
_clientInfo.restore();
_killClient.restore();
_clientList.restore();
});
it('the list have two clients with the same name Should kill one', async () => {
helper._settings.name = 'test_service_api_0'
await helper._verifyUniqueConnection(true);
expect(_clientInfo.calledOnce).to.be.true;
expect(_clientList.calledOnce).to.be.true;
expect(_killClient.calledOnce).to.be.true;
});
it('the list have no clients duplicated with the same name Should kill no one', async () => {
helper._settings.name = 'test_service_api_1'
await helper._verifyUniqueConnection(true);
expect(_clientInfo.calledOnce).to.be.true;
expect(_clientList.calledOnce).to.be.true;
expect(_killClient.calledOnce).to.be.false;
});
it('the list have unnamed clients just created it Should kill no one', async () => {
helper._settings.name = 'test_service_api_1'
ClienList.push('id=8104296001004 addr=186.99.6.38:58898 laddr=172.16.0.38:12726 fd=4501 name= age=1 idle=1 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=2147483647 obl=0 oll=0 omem=0 totMem=0 events=r cmd=CLIENT user=default redir=r\r')
await helper._verifyUniqueConnection(true);
expect(_clientInfo.calledOnce).to.be.true;
expect(_clientList.calledOnce).to.be.true;
expect(_killClient.calledOnce).to.be.false;
});
it('the list have one unnamed clients old aged it Should kill one', async () => {
helper._settings.name = 'test_service_api_1'
ClienList.push('id=8104296001005 addr=186.99.6.38:58898 laddr=172.16.0.38:12726 fd=4501 name= age=200 idle=1 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=2147483647 obl=0 oll=0 omem=0 totMem=0 events=r cmd=CLIENT user=default redir=r\r')
await helper._verifyUniqueConnection(true);
expect(_clientInfo.calledOnce).to.be.true;
expect(_clientList.calledOnce).to.be.true;
expect(_killClient.calledOnce).to.be.true;
});
});
describe('When call _killClient', () => {
let clientKill = {};
beforeEach(() => {
helper._client = {
clientKill: () => { },
};
clientKill = sinon.stub(helper._client, "clientKill").callsFake(() => { });
});
afterEach(() => {
clientKill.restore();
});
it('when id is null it Should not call to clientKill', async () => {
await helper._killClient('');
expect(clientKill.calledOnce).to.be.false;
});
it('when id is not null it Should call to clientKill', async () => {
const id = 23
await helper._killClient(id);
expect(clientKill.calledOnce).to.be.true;
expect(clientKill.getCalls()[0].args).be.deep.equal([{ filter: 'ID', id: id }]);
});
});
describe('When call _clientInfo or _clientList', () => {
let sendCommand = {};
beforeEach(() => {
helper._client = {
sendCommand: () => { }
};
sendCommand = sinon.stub(helper._client, "sendCommand").callsFake(() => { });
});
afterEach(() => {
sendCommand.restore();
});
it('when _clientList is called it Should call to sendCommand with rigth params', async () => {
sendCommand.returns(ClienList.join('\n'))
await helper._clientList();
expect(sendCommand.calledOnce).to.be.true;
expect(sendCommand.getCalls()[0].args).be.deep.equal([['CLIENT', 'LIST']]);
});
it('when _clientInfo is called it Should call to sendCommand with rigth params', async () => {
await helper._clientInfo();
expect(sendCommand.calledOnce).to.be.true;
expect(sendCommand.getCalls()[0].args).be.deep.equal([['CLIENT', 'INFO']]);
});
});
});