3535const errors = require ( '../../../lib/constants/errors' ) ;
3636const expect = require ( 'chai' ) . expect ;
3737const td = require ( 'testdouble' ) ;
38- const tk = require ( 'timekeeper' ) ;
3938const util = require ( 'util' ) ;
4039
4140// subject under test needs to be reloaded with replacement fakes
@@ -44,7 +43,6 @@ let connectionPool = require('../../../lib/DevAPI/ConnectionPool');
4443describe ( 'ConnectionPool' , ( ) => {
4544 afterEach ( 'reset fakes' , ( ) => {
4645 td . reset ( ) ;
47- tk . reset ( ) ;
4846 } ) ;
4947
5048 context ( 'create()' , ( ) => {
@@ -141,30 +139,6 @@ describe('ConnectionPool', () => {
141139 connectionPool = require ( '../../../lib/DevAPI/ConnectionPool' ) ;
142140 } ) ;
143141
144- it ( 'fails if queueTimeout was exceeded' , done => {
145- const queueTimeout = 5000 ;
146- const pool = connectionPool ( { pooling : { maxSize : 3 , queueTimeout } } ) . create ( { active : [ 'foo' , 'bar' , 'baz' ] } ) ;
147- const isAvailable = td . replace ( pool , 'isAvailable' ) ;
148- const update = td . replace ( pool , 'update' ) ;
149-
150- td . when ( update ( ) ) . thenResolve ( ) ;
151- td . when ( isAvailable ( ) ) . thenReturn ( true ) ;
152-
153- // We need to travel in time only after calling
154- // pool.getConnection(), otherwise, Date.now() will also be in the
155- // future.
156- pool . getConnection ( )
157- . then ( ( ) => {
158- done ( expect . fail ( ) ) ;
159- } )
160- . catch ( err => {
161- expect ( err . message ) . to . equal ( util . format ( errors . MESSAGES . ER_DEVAPI_POOL_QUEUE_TIMEOUT , queueTimeout ) ) ;
162- done ( ) ;
163- } ) ;
164-
165- tk . travel ( new Date ( Date . now ( ) + queueTimeout + 1 ) ) ;
166- } ) ;
167-
168142 it ( 'acquires and returns an idle connection if one exists and no expired ones exist' , ( ) => {
169143 const poolConnection = { acquire, isClosing, isExpired, isOpen, override } ;
170144 const pool = connectionPool ( { pooling : { maxSize : 3 } } ) . create ( { active : [ 'foo' ] , idle : [ poolConnection ] } ) ;
@@ -281,61 +255,109 @@ describe('ConnectionPool', () => {
281255 } ) ;
282256 } ) ;
283257
284- it ( 'queues the request when the pool is full and queueTimeout was not exceeded' , done => {
285- const queueTimeout = 1000 ;
286- const options = { pooling : { maxSize : 3 , queueTimeout } } ;
287- const pool = connectionPool ( options ) . create ( { active : [ 'foo' , 'bar' , 'baz' ] } ) ;
288- const isAvailable = td . replace ( pool , 'isAvailable' ) ;
289- const update = td . replace ( pool , 'update' ) ;
290- const poolConnection = { acquire } ;
258+ context ( 'when the pool is full' , ( ) => {
259+ let system ;
291260
292- td . when ( update ( ) ) . thenResolve ( ) ;
293- td . when ( isAvailable ( ) ) . thenReturn ( true ) ;
294- td . when ( connection ( options ) ) . thenReturn ( { open } ) ;
295- td . when ( open ( ) ) . thenResolve ( poolConnection ) ;
296-
297- // We need to travel in time only after calling
298- // pool.getConnection(), otherwise, Date.now() will also be in the
299- // future.
300- pool . getConnection ( ) . then ( con => {
301- expect ( td . explain ( acquire ) . callCount ) . to . equal ( 1 ) ;
302- expect ( pool . activeConnections ( ) ) . to . deep . include ( con ) ;
303- expect ( con ) . to . deep . equal ( poolConnection ) ;
261+ beforeEach ( 'setup fake time' , ( ) => {
262+ system = td . replace ( '../../../lib/system' ) ;
304263
305- return done ( ) ;
264+ connectionPool = require ( '../../../lib/DevAPI/ConnectionPool' ) ;
306265 } ) ;
307266
308- tk . travel ( new Date ( Date . now ( ) + queueTimeout / 10 + 1 ) ) ;
309- // We reset the pool after queueTimeout / 10.
310- setTimeout ( ( ) => pool . reset ( ) , queueTimeout / 10 ) ;
311- } ) ;
312-
313- it ( 'queues the request when an an expired connection is available but is still being closed and queueTimeout was not exceeded' , done => {
314- const queueTimeout = 1000 ;
315- const options = { pooling : { maxSize : 3 , queueTimeout } } ;
316- const pool = connectionPool ( options ) . create ( { active : [ 'foo' , 'bar' ] , expired : [ { isClosing } ] } ) ;
317- const isAvailable = td . replace ( pool , 'isAvailable' ) ;
318- const update = td . replace ( pool , 'update' ) ;
319- const poolConnection = { acquire } ;
267+ it ( 'queues the request if queueTimeout was not exceeded' , done => {
268+ const queueTimeout = 1000 ;
269+ const options = { pooling : { maxSize : 3 , queueTimeout } } ;
270+ const pool = connectionPool ( options ) . create ( { active : [ 'foo' , 'bar' , 'baz' ] } ) ;
271+ const isAvailable = td . replace ( pool , 'isAvailable' ) ;
272+ const update = td . replace ( pool , 'update' ) ;
273+ const poolConnection = { acquire } ;
274+ const now = Date . now ( ) ;
275+
276+ // The last time it is called, system.time() should return a time
277+ // after queueTimeout.
278+ td . when ( system . time ( ) ) . thenReturn ( now + queueTimeout / 10 + 1 ) ;
279+ // The first time it is called, system.time() should return the
280+ // initial time.
281+ td . when ( system . time ( ) , { times : 1 } ) . thenReturn ( now ) ;
282+ td . when ( update ( ) ) . thenResolve ( ) ;
283+ td . when ( isAvailable ( ) ) . thenReturn ( true ) ;
284+ td . when ( connection ( options ) ) . thenReturn ( { open } ) ;
285+ td . when ( open ( ) ) . thenResolve ( poolConnection ) ;
286+
287+ // We need to travel in time only after calling
288+ // pool.getConnection(), otherwise, Date.now() will also be in the
289+ // future.
290+ pool . getConnection ( ) . then ( con => {
291+ expect ( td . explain ( acquire ) . callCount ) . to . equal ( 1 ) ;
292+ expect ( pool . activeConnections ( ) ) . to . deep . include ( con ) ;
293+ expect ( con ) . to . deep . equal ( poolConnection ) ;
320294
321- td . when ( update ( ) ) . thenResolve ( ) ;
322- td . when ( isAvailable ( ) ) . thenReturn ( true ) ;
323- td . when ( isClosing ( ) ) . thenReturn ( true ) ;
324- td . when ( connection ( options ) ) . thenReturn ( { open } ) ;
325- td . when ( open ( ) ) . thenResolve ( poolConnection ) ;
295+ return done ( ) ;
296+ } ) ;
326297
327- // We need to travel in time only after calling
328- // pool.getConnection(), otherwise, Date.now() will also be in the
329- // future.
330- pool . getConnection ( ) . then ( con => {
331- expect ( td . explain ( acquire ) . callCount ) . to . equal ( 1 ) ;
332- expect ( pool . activeConnections ( ) ) . to . deep . include ( con ) ;
333- expect ( con ) . to . deep . equal ( poolConnection ) ;
298+ // We reset the pool after queueTimeout / 10.
299+ setTimeout ( ( ) => pool . reset ( ) , queueTimeout / 10 ) ;
300+ } ) ;
334301
335- return done ( ) ;
302+ it ( 'queues the request when an an expired connection is available but is still being closed and queueTimeout was not exceeded' , ( ) => {
303+ const queueTimeout = 1000 ;
304+ const options = { pooling : { maxSize : 3 , queueTimeout } } ;
305+ const pool = connectionPool ( options ) . create ( { active : [ 'foo' , 'bar' ] , expired : [ { isClosing } ] } ) ;
306+ const isAvailable = td . replace ( pool , 'isAvailable' ) ;
307+ const update = td . replace ( pool , 'update' ) ;
308+ const poolConnection = { acquire } ;
309+ const now = Date . now ( ) ;
310+
311+ // The last time it is called, system.time() should return a time
312+ // after queueTimeout.
313+ td . when ( system . time ( ) ) . thenReturn ( now + queueTimeout / 10 + 1 ) ;
314+ // The first time it is called, system.time() should return the
315+ // initial time.
316+ td . when ( system . time ( ) , { times : 1 } ) . thenReturn ( now ) ;
317+ td . when ( update ( ) ) . thenResolve ( ) ;
318+ td . when ( isAvailable ( ) ) . thenReturn ( true ) ;
319+ td . when ( isClosing ( ) ) . thenReturn ( true ) ;
320+ td . when ( connection ( options ) ) . thenReturn ( { open } ) ;
321+ td . when ( open ( ) ) . thenResolve ( poolConnection ) ;
322+
323+ // We need to travel in time only after calling
324+ // pool.getConnection(), otherwise, Date.now() will also be in the
325+ // future.
326+ return pool . getConnection ( )
327+ . then ( con => {
328+ expect ( td . explain ( acquire ) . callCount ) . to . equal ( 1 ) ;
329+ expect ( pool . activeConnections ( ) ) . to . deep . include ( con ) ;
330+ return expect ( con ) . to . deep . equal ( poolConnection ) ;
331+ } ) ;
336332 } ) ;
337333
338- tk . travel ( new Date ( Date . now ( ) + queueTimeout / 10 + 1 ) ) ;
334+ it ( 'fails when queueTimeout is exceeded' , ( ) => {
335+ const queueTimeout = 5000 ;
336+ const pool = connectionPool ( { pooling : { maxSize : 3 , queueTimeout } } ) . create ( { active : [ 'foo' , 'bar' , 'baz' ] } ) ;
337+ const isAvailable = td . replace ( pool , 'isAvailable' ) ;
338+ const update = td . replace ( pool , 'update' ) ;
339+ const now = Date . now ( ) ;
340+
341+ // The last time it is called, system.time() should return a time
342+ // after queueTimeout.
343+ td . when ( system . time ( ) ) . thenReturn ( now + queueTimeout + 1 ) ;
344+ // The first time it is called, system.time() should return the
345+ // initial time.
346+ td . when ( system . time ( ) , { times : 1 } ) . thenReturn ( now ) ;
347+ td . when ( update ( ) ) . thenResolve ( ) ;
348+ td . when ( isAvailable ( ) ) . thenReturn ( true ) ;
349+
350+ // We need to travel in time only after calling
351+ // pool.getConnection(), otherwise, Date.now() will also be in the
352+ // future.
353+ return pool . getConnection ( )
354+ . then ( ( ) => {
355+ return expect . fail ( ) ;
356+ } )
357+ . catch ( err => {
358+ return expect ( err . message ) . to . equal ( util . format ( errors . MESSAGES . ER_DEVAPI_POOL_QUEUE_TIMEOUT , queueTimeout ) ) ;
359+ } ) ;
360+ } ) ;
339361 } ) ;
340362
341363 it ( 'does not re-use any connection when the pool is not available' , ( ) => {
0 commit comments