'use strict'; var assert = require('assert'); var config = require('./lib/config'); var fs = require('fs'); var helper = require('./helper'); var path = require('path'); var redis = config.redis; var utils = require('../lib/utils'); var tls = require('tls'); var tls_options = { servername: 'redis.js.org', rejectUnauthorized: true, ca: [ String(fs.readFileSync(path.resolve(__dirname, './conf/redis.js.org.cert'))) ] }; var tls_port = 6380; // Use skip instead of returning to indicate what tests really got skipped var skip = false; describe('TLS connection tests', function () { before(function (done) { // Print the warning when the tests run instead of while starting mocha if (process.platform === 'win32') { skip = true; console.warn('\nStunnel tests do not work on windows atm. If you think you can fix that, it would be warmly welcome.\n'); } if (skip) return done(); helper.stopStunnel(function () { helper.startStunnel(done); }); }); after(function (done) { if (skip) return done(); helper.stopStunnel(done); }); var client; afterEach(function () { if (skip) return; client.end(true); }); describe('on lost connection', function () { it('emit an error after max retry timeout and do not try to reconnect afterwards', function (done) { if (skip) this.skip(); var connect_timeout = 500; // in ms client = redis.createClient({ connect_timeout: connect_timeout, port: tls_port, tls: utils.clone(tls_options) }); var time = 0; assert.strictEqual(client.address, '127.0.0.1:' + tls_port); client.once('ready', function () { helper.killConnection(client); }); client.on('reconnecting', function (params) { time += params.delay; }); client.on('error', function (err) { if (/Redis connection in broken state: connection timeout.*?exceeded./.test(err.message)) { process.nextTick(function () { assert.strictEqual(time, connect_timeout); assert.strictEqual(client.emitted_end, true); assert.strictEqual(client.connected, false); assert.strictEqual(client.ready, false); assert.strictEqual(client.closing, true); assert.strictEqual(time, connect_timeout); done(); }); } }); }); }); describe('when not connected', function () { it('connect with host and port provided in the tls object', function (done) { if (skip) this.skip(); var tls_opts = utils.clone(tls_options); tls_opts.port = tls_port; tls_opts.host = 'localhost'; client = redis.createClient({ connect_timeout: 1000, tls: tls_opts }); // verify connection is using TCP, not UNIX socket assert.strictEqual(client.connection_options.host, 'localhost'); assert.strictEqual(client.connection_options.port, tls_port); assert.strictEqual(client.address, 'localhost:' + tls_port); assert(client.stream.encrypted); client.set('foo', 'bar'); client.get('foo', helper.isString('bar', done)); }); describe('using rediss as url protocol', function () { var tls_connect = tls.connect; beforeEach(function () { tls.connect = function (options) { options = utils.clone(options); options.ca = tls_options.ca; options.servername = 'redis.js.org'; options.rejectUnauthorized = true; return tls_connect.call(tls, options); }; }); afterEach(function () { tls.connect = tls_connect; }); it('connect with tls when rediss is used as the protocol', function (done) { if (skip) this.skip(); client = redis.createClient('rediss://localhost:' + tls_port); // verify connection is using TCP, not UNIX socket assert(client.stream.encrypted); client.set('foo', 'bar'); client.get('foo', helper.isString('bar', done)); }); }); it('fails to connect because the cert is not correct', function (done) { if (skip) this.skip(); var faulty_cert = utils.clone(tls_options); faulty_cert.ca = [ String(fs.readFileSync(path.resolve(__dirname, './conf/faulty.cert'))) ]; client = redis.createClient({ host: 'localhost', connect_timeout: 1000, port: tls_port, tls: faulty_cert }); assert.strictEqual(client.address, 'localhost:' + tls_port); client.on('error', function (err) { assert(/DEPTH_ZERO_SELF_SIGNED_CERT/.test(err.code || err.message), err); client.end(true); }); client.set('foo', 'bar', function (err, res) { done(res); }); }); }); });