@@ -301,6 +301,182 @@ describe('compression()', function () {
301301 . expect ( 200 , done )
302302 } )
303303
304+ it ( 'should support removeListener("drain") after on("drain"); stream present' , function ( done ) {
305+ // compression doesn't proxy listenerCount() to the compression stream, so
306+ // instead watch for a MaxListenersExceededWarning
307+ var hasWarned = false
308+ var onWarning = function ( ) {
309+ hasWarned = true
310+ }
311+ process . on ( 'warning' , onWarning )
312+ var server = createServer ( { threshold : 0 } , function ( req , res ) {
313+ res . setHeader ( 'Content-Type' , 'text/plain' )
314+ var len = bytes ( '40kb' )
315+ var buf = Buffer . alloc ( len , '.' )
316+ res . write ( buf )
317+ for ( var times = 0 ; times < res . getMaxListeners ( ) + 1 ; times ++ ) {
318+ var listener = function ( ) { }
319+ res . on ( 'drain' , listener )
320+ res . removeListener ( 'drain' , listener )
321+ }
322+ res . end ( )
323+ } )
324+
325+ request ( server )
326+ . get ( '/' )
327+ . set ( 'Accept-Encoding' , 'gzip' )
328+ . expect ( function ( ) {
329+ process . removeListener ( 'warning' , onWarning )
330+ assert . ok ( ! hasWarned )
331+ } )
332+ . expect ( 200 , done )
333+ } )
334+
335+ it ( 'should support removeListener("drain") after addListener("drain")' , function ( done ) {
336+ var hasWarned = false
337+ var onWarning = function ( ) {
338+ hasWarned = true
339+ }
340+ process . on ( 'warning' , onWarning )
341+ var server = createServer ( { threshold : 0 } , function ( req , res ) {
342+ res . setHeader ( 'Content-Type' , 'text/plain' )
343+ var len = bytes ( '40kb' )
344+ var buf = Buffer . alloc ( len , '.' )
345+ res . write ( buf )
346+ for ( var times = 0 ; times < res . getMaxListeners ( ) + 1 ; times ++ ) {
347+ var listener = function ( ) { }
348+ res . addListener ( 'drain' , listener )
349+ res . removeListener ( 'drain' , listener )
350+ }
351+ res . end ( )
352+ } )
353+
354+ request ( server )
355+ . get ( '/' )
356+ . set ( 'Accept-Encoding' , 'gzip' )
357+ . expect ( function ( ) {
358+ process . removeListener ( 'warning' , onWarning )
359+ assert . ok ( ! hasWarned )
360+ } )
361+ . expect ( 200 , done )
362+ } )
363+
364+ it ( 'should support off("drain") after addListener("drain")' , function ( done ) {
365+ var hasWarned = false
366+ var onWarning = function ( ) {
367+ hasWarned = true
368+ }
369+ process . on ( 'warning' , onWarning )
370+ var server = createServer ( { threshold : 0 } , function ( req , res ) {
371+ res . setHeader ( 'Content-Type' , 'text/plain' )
372+ var len = bytes ( '40kb' )
373+ var buf = Buffer . alloc ( len , '.' )
374+ res . write ( buf )
375+ for ( var times = 0 ; times < res . getMaxListeners ( ) + 1 ; times ++ ) {
376+ var listener = function ( ) { }
377+ res . addListener ( 'drain' , listener )
378+ res . off ( 'drain' , listener )
379+ }
380+ res . end ( )
381+ } )
382+
383+ request ( server )
384+ . get ( '/' )
385+ . set ( 'Accept-Encoding' , 'gzip' )
386+ . expect ( function ( ) {
387+ process . removeListener ( 'warning' , onWarning )
388+ assert . ok ( ! hasWarned )
389+ } )
390+ . expect ( 200 , done )
391+ } )
392+
393+ it ( 'should support removeListener("drain"); buffered' , function ( done ) {
394+ // Variant of above tests for scenario when the listener is buffered (stream
395+ // is not yet present).
396+ var hasWarned = false
397+ var onWarning = function ( ) {
398+ hasWarned = true
399+ }
400+ process . on ( 'warning' , onWarning )
401+ var server = createServer ( { threshold : 0 } , function ( req , res ) {
402+ res . setHeader ( 'Content-Type' , 'text/plain' )
403+ for ( var times = 0 ; times < res . getMaxListeners ( ) + 1 ; times ++ ) {
404+ var listener = function ( ) { }
405+ res . on ( 'drain' , listener )
406+ res . removeListener ( 'drain' , listener )
407+ }
408+ res . end ( )
409+ } )
410+
411+ request ( server )
412+ . get ( '/' )
413+ . set ( 'Accept-Encoding' , 'gzip' )
414+ . expect ( function ( ) {
415+ process . removeListener ( 'warning' , onWarning )
416+ assert . ok ( ! hasWarned )
417+ } )
418+ . expect ( 200 , done )
419+ } )
420+
421+ it ( 'should support removeListener("drain"); multiple bindings of same listener, buffered' , function ( done ) {
422+ // Variant of above test for scenario when the listener is buffered (stream
423+ // is not yet present) and the same listener is added two or more times.
424+ var hasWarned = false
425+ var onWarning = function ( ) {
426+ hasWarned = true
427+ }
428+ process . on ( 'warning' , onWarning )
429+ var server = createServer ( { threshold : 0 } , function ( req , res ) {
430+ res . setHeader ( 'Content-Type' , 'text/plain' )
431+ for ( var times = 0 ; times < res . getMaxListeners ( ) + 1 ; times ++ ) {
432+ var listener = function ( ) { }
433+ res . on ( 'drain' , listener )
434+ res . on ( 'drain' , listener )
435+ res . removeListener ( 'drain' , listener )
436+ }
437+ res . end ( )
438+ } )
439+
440+ request ( server )
441+ . get ( '/' )
442+ . set ( 'Accept-Encoding' , 'gzip' )
443+ . expect ( function ( ) {
444+ process . removeListener ( 'warning' , onWarning )
445+ assert . ok ( ! hasWarned )
446+ } )
447+ . expect ( 200 , done )
448+ } )
449+
450+ it ( 'should not leak event listeners when res.unpipe() is used (#135)' , function ( done ) {
451+ var hasWarned = false
452+ var onWarning = function ( ) {
453+ hasWarned = true
454+ }
455+ var server = createServer ( { threshold : 0 } , function ( req , res ) {
456+ var times = 0
457+ var int = setInterval ( function ( ) {
458+ var rs = require ( 'fs' ) . createReadStream ( 'does not exist' )
459+ rs . on ( 'error' , function ( e ) {
460+ rs . unpipe ( res )
461+ } )
462+ rs . pipe ( res )
463+ if ( times ++ > res . getMaxListeners ( ) ) {
464+ clearInterval ( int )
465+ res . end ( 'hello, world' )
466+ }
467+ } )
468+ } )
469+
470+ request ( server )
471+ . get ( '/' )
472+ . set ( 'Accept-Encoding' , 'gzip' )
473+ . expect ( function ( ) {
474+ process . removeListener ( 'warning' , onWarning )
475+ assert . ok ( ! hasWarned )
476+ } )
477+ . expect ( 200 , done )
478+ } )
479+
304480 describe ( 'threshold' , function ( ) {
305481 it ( 'should not compress responses below the threshold size' , function ( done ) {
306482 var server = createServer ( { threshold : '1kb' } , function ( req , res ) {
0 commit comments