UNPKG

core

Version:

Core Libs

479 lines (391 loc) 19.4 kB
var rewire = require('rewire'); var modulePath = '../../lib/client/PGPool.js'; describe('PGPool', function () { describe('require', function () { it ('should be truthy', function () { var PGPool = require(modulePath).PGPool; expect(PGPool).toBeTruthy(); }); it('should not throw exception ',function () { expect(function () { var PGPool = require(modulePath).PGPool; }).not.toThrow(); }); }); describe('methods', function () { var PGPoolMock; var PGPool; beforeEach(function () { PGPoolMock = rewire(modulePath); PGPool = PGPoolMock.PGPool; }); describe('_handleConnectionCount', function () { beforeEach(function () { this.instance = new PGPool(); this.instance.setMaxLength(10); this.instance._createConnections = jasmine.createSpy('_createConnections'); this.instance._removeConnections = jasmine.createSpy('_removeConnections'); }); describe('when connection shortated', function () { beforeEach(function () { spyOn(this.instance, 'getKnownLength').andReturn(5); this.instance._handleConnectionCount(); }) it('should call _createConnections', function () { expect(this.instance._createConnections).toHaveBeenCalled(); }); }); describe('when connection overhead', function () { beforeEach(function () { spyOn(this.instance, 'getKnownLength').andReturn(15); this.instance._handleConnectionCount(); }) it('should call _removeConnections', function () { expect(this.instance._removeConnections).toHaveBeenCalled(); }); }); }); describe('_createConnections', function () { var retValue = null; beforeEach(function () { this.instance = new PGPool(); spyOn(this.instance, '_createConnection').andCallFake(function (cfg, cb) { cb(retValue); }); spyOn(this.instance, 'scheduleRenew').andReturn(null);; }); describe('many connections', function () { beforeEach(function () { this.instance._createConnections(5); }); it('should try to create connections', function () { expect(this.instance._createConnection.callCount).toEqual(5); }); it('should not call scheduleRenew', function () { expect(this.instance.scheduleRenew).not.toHaveBeenCalled(); }); }); describe('when errror', function () { beforeEach(function () { retValue = 'error'; this.instance._createConnections(5); }); it('should try to create connections', function () { expect(this.instance._createConnection.callCount).toEqual(5); }); it('should not call scheduleRenew', function () { expect(this.instance.scheduleRenew).toHaveBeenCalled(); }); }); }); describe('_createConnection', function () { var PGClient; var EventEmitter = require('events').EventEmitter; var ClientMock = function (config) { EventEmitter.call(this); }; ClientMock.prototype = Object.create(EventEmitter.prototype); ClientMock.prototype.connect = function () {}; ClientMock.prototype.end = function () {}; beforeEach(function () { PGPoolMock.__set__('PGClient', ClientMock); this.instance = new PGPool(); }); describe('on success', function () { beforeEach(function () { spyOn(ClientMock.prototype, 'connect').andCallFake(function () { this.emit('connect', null); }) spyOn(ClientMock.prototype, 'removeListener'); this.callback = jasmine.createSpy('callback'); this.instance._createConnection({}, this.callback); }); it('should add client to pool', function () { expect(this.instance.getKnownLength()).toEqual(1); }); it('should spawn callback', function () { expect(this.callback).toHaveBeenCalled(); }); }); }); describe('_removeConnections', function () { var EventEmitter = require('events').EventEmitter; var ClientMock = function (config) { EventEmitter.call(this); }; ClientMock.prototype = Object.create(EventEmitter.prototype); ClientMock.prototype.connect = function () {}; ClientMock.prototype.end = jasmine.createSpy('ClientMock.end'); beforeEach(function () { this.instance = new PGPool(); }); afterEach(function () { this.instance.destroy(); }); describe('many clients', function () { beforeEach(function () { spyOn(this.instance, 'get').andCallThrough(); this.instance.add(new ClientMock()); this.instance.add(new ClientMock()); this.instance.add(new ClientMock()); this.instance._removeConnections(2); }); it('should try to get clients from pool', function () { expect(this.instance.get).toHaveBeenCalled(); }); it('should try to get given number of clients', function () { expect(this.instance.get.callCount).toEqual(2); }); it('should try to remove given number of clients', function () { expect(this.instance.getKnownLength()).toEqual(1); }); }); describe('when no clients', function () { beforeEach(function () { spyOn(this.instance, 'get').andCallThrough(); this.instance._removeConnections(2); }); it('should not try to get clients', function () { expect(this.instance.get).not.toHaveBeenCalled(); }); }); describe('operations on client', function () { beforeEach(function () { this.client = new ClientMock(); this.instance.add(this.client); this.instance._removeConnections(1); }); it('should end clients connection', function () { expect(this.client.end).toHaveBeenCalled(); }); }); }); describe('query', function () { var retErr; var retData; beforeEach(function () { this.instance = new PGPool(); var clientMock = { query: function (sql, params, callback) { callback(retErr, retData); } } spyOn(this.instance, 'get').andCallFake(function (callback) { callback(clientMock); }); }); describe('when no error', function () { beforeEach(function () { retErr = null; retData = 'data'; this.callback = jasmine.createSpy('queryCallback'); this.instance.query('sql', 'params', this.callback); }); it('should spawn callback', function () { expect(this.callback).toHaveBeenCalled(); }); it('should return data in callback', function () { expect(this.callback.mostRecentCall.args[1]).toEqual(retData); }); it('should not return error in callback', function () { expect(this.callback.mostRecentCall.args[0]).toBeNull(); }); it('should not put query to queue', function () { expect(this.instance._queuedQueries.length).toEqual(0); }); }); describe('when error', function () { beforeEach(function () { retErr = new Error('Query error'); retData = null; spyOn(PGPool.prototype, '_isFatalError').andReturn(false); this.callback = jasmine.createSpy('queryCallback'); this.instance.query('sql', 'params', this.callback); }); it('should spawn callback', function () { expect(this.callback).toHaveBeenCalled(); }); it('should return data in callback', function () { expect(this.callback.mostRecentCall.args[1]).toEqual(retData); }); it('should return error in callback', function () { expect(this.callback.mostRecentCall.args[0]).toEqual(retErr); }); it('should not put query to queue', function () { expect(this.instance._queuedQueries.length).toEqual(0); }); }); describe('when fatal error', function () { beforeEach(function () { retErr = new Error('Fatal error'); retData = null; spyOn(PGPool.prototype, '_isFatalError').andReturn(true); spyOn(this.instance, '_removeClient'); this.callback = jasmine.createSpy('queryCallback'); }); afterEach(function () { this.instance.destroy(); }); describe('limit not reached', function () { beforeEach(function () { this.instance.query('sql', 'params', this.callback, 1); }); it('should not spawn callback', function () { expect(this.callback).not.toHaveBeenCalled(); }); it('should put query to queue', function () { expect(this.instance._queuedQueries.length).toEqual(1); }); it('should remove broken client', function () { expect(this.instance._removeClient).toHaveBeenCalled(); }); }); describe('limit reached', function () { beforeEach(function () { this.instance.query('sql', 'params', this.callback, 5); }); it('should spawn callback', function () { expect(this.callback).toHaveBeenCalled(); }); it('should not put query to queue', function () { expect(this.instance._queuedQueries.length).toEqual(0); }); it('should remove broken client', function () { expect(this.instance._removeClient).toHaveBeenCalled(); }); }); }); }); describe('queryWithCursors', function () { var ClientMock = function (config) {}; ClientMock.prototype.query = function () {}; ClientMock.prototype.end = jasmine.createSpy('ClientMock.end'); beforeEach(function () { this.instance = new PGPool(); this.client = new ClientMock(); this.instance.add(this.client); }); afterEach(function () { this.instance.destroy(); }); describe('when error during transaction', function () { var methodQuery = 'SELECT * FROM api.get_users()'; describe('after BEGIN', function () { beforeEach(function () { spyOn(this.client, 'query').andCallFake(function (sql, params, callback) { if (sql == 'BEGIN') return callback('error', null); return callback(null, 'data'); }); this.callback = jasmine.createSpy('query_callback'); this.instance.queryWithCursors(methodQuery, [], ['entries'], this.callback); }); it('should release client to pool', function () { expect(this.instance.getSpareLength()).toEqual(1); }); it('should spawn callback with error', function () { expect(this.callback).toHaveBeenCalled(); expect(this.callback).toHaveBeenCalledWith('error', null); }); it('should call 2 queries', function () { expect(this.client.query.callCount).toEqual(2); }); it('should end transaction', function () { expect(this.client.query.mostRecentCall.args[0]).toEqual('COMMIT'); }); }); describe('after method call', function () { beforeEach(function () { spyOn(this.client, 'query').andCallFake(function (sql, params, callback) { if (sql == methodQuery) return callback('error', null); return callback(null, 'data'); }); this.callback = jasmine.createSpy('query_callback'); this.instance.queryWithCursors(methodQuery, [], ['entries'], this.callback); }); it('should release client to pool', function () { expect(this.instance.getSpareLength()).toEqual(1); }); it('should spawn callback with error', function () { expect(this.callback).toHaveBeenCalled(); expect(this.callback).toHaveBeenCalledWith('error', null); }); it('should call 3 queries', function () { expect(this.client.query.callCount).toEqual(3); }); it('should end transaction', function () { expect(this.client.query.mostRecentCall.args[0]).toEqual('COMMIT'); }); }); }); describe('when no error', function () { var methodQuery = 'SELECT * FROM api.get_users()'; describe('when empty result from procedure', function () { var methodResult; beforeEach(function () { methodResult = JSON.parse('{"rowCount":0,"rows":[]}'); spyOn(this.client, 'query').andCallFake(function (sql, params, callback) { if (sql == methodQuery) return callback(null, methodResult); return callback(null, 'data'); }); this.callback = jasmine.createSpy('query_callback'); this.instance.queryWithCursors(methodQuery, [], ['entries'], this.callback); }); it('should return original result', function () { expect(this.callback).toHaveBeenCalledWith(null, methodResult); }); it('should end transaction', function () { expect(this.client.query.mostRecentCall.args[0]).toEqual('COMMIT'); }); it('should release client to pool', function () { expect(this.instance.getSpareLength()).toEqual(1); }); }); describe('when normal result from procedure', function () { var methodResult; var cursorResult; beforeEach(function () { methodResult = JSON.parse('{"rowCount":1,"rows":[{"status":"OK","entries":"hits"}]}'); cursorResult = JSON.parse('{"rowCount":2,"rows":[{"id":1,"name":"stefan"},{"id":2,"name":"marian"}]}'); spyOn(this.client, 'query').andCallFake(function (sql, params, callback) { if (sql == methodQuery) return callback(null, methodResult); else if (sql == 'FETCH ALL FROM "hits"') return callback(null, cursorResult); else return callback(null, 'data'); }); this.callback = jasmine.createSpy('query_callback'); this.instance.queryWithCursors(methodQuery, [], ['entries'], this.callback); }); it('should spawn callback', function () { expect(this.callback).toHaveBeenCalled(); }); it('should end transaction', function () { expect(this.client.query.mostRecentCall.args[0]).toEqual('COMMIT'); }); it('should release client to pool', function () { expect(this.instance.getSpareLength()).toEqual(1); }); describe('result', function () { beforeEach(function () { this.result = this.callback.mostRecentCall.args[1]; }); it('should be defined', function () { expect(this.result).toBeDefined(); }); it('should have one row', function () { expect(this.result.rowCount).toEqual(1); expect(this.result.rows.length).toEqual(1); }); it('should be filled with data from cursor', function () { expect(this.result.rows[0].entries).toEqual(cursorResult.rows); }); }); }); }); }); }); });