44// (matching every other Writable), not the moment respondWithFD was called.
55//
66// - Clean EOF: 'finish' fires, writableFinished=true.
7- // - Peer aborts mid-pipe: 'finish' does NOT fire, writableFinished stays
8- // false. ('aborted' is preserved per its legacy criterion: writable was
9- // 'ending' at close, so it doesn't fire here either way.)
7+ // - Aborted before pipe completes: 'finish' does NOT fire,
8+ // writableFinished stays false. ('aborted' is preserved per its
9+ // legacy criterion: writable was 'ending' at close, so it doesn't
10+ // fire either way.)
1011
1112const common = require ( '../common' ) ;
1213if ( ! common . hasCrypto )
@@ -16,12 +17,8 @@ const fs = require('fs');
1617const path = require ( 'path' ) ;
1718const http2 = require ( 'http2' ) ;
1819const tmpdir = require ( '../common/tmpdir' ) ;
19- const { NGHTTP2_CANCEL } = http2 . constants ;
2020
2121tmpdir . refresh ( ) ;
22- const bigPath = path . join ( tmpdir . path , 'big.bin' ) ;
23- const bigSize = 1024 * 1024 ; // 1 MiB - well over initial flow-control window
24- fs . writeFileSync ( bigPath , Buffer . alloc ( bigSize ) ) ;
2522
2623function testCleanCompletion ( next ) {
2724 const smallPath = path . join ( tmpdir . path , 'small.bin' ) ;
@@ -59,7 +56,11 @@ function testCleanCompletion(next) {
5956 } ) ) ;
6057}
6158
62- function testPeerAbort ( ) {
59+ function testAbortBeforeCompletion ( ) {
60+ const smallPath = path . join ( tmpdir . path , 'small-abort.bin' ) ;
61+ const smallSize = 64 ;
62+ fs . writeFileSync ( smallPath , Buffer . alloc ( smallSize ) ) ;
63+
6364 const server = http2 . createServer ( ) ;
6465 server . on ( 'stream' , common . mustCall ( ( stream ) => {
6566 stream . on ( 'finish' , common . mustNotCall (
@@ -71,9 +72,11 @@ function testPeerAbort() {
7172 // writableFinished must reflect actual pipe completion.
7273 assert . strictEqual ( stream . writableFinished , false ) ;
7374 } ) ) ;
74- const fd = fs . openSync ( bigPath , 'r' ) ;
75+ const fd = fs . openSync ( smallPath , 'r' ) ;
7576 stream . ownsFd = true ;
76- stream . respondWithFD ( fd , { 'content-length' : bigSize } ) ;
77+ stream . respondWithFD ( fd , { 'content-length' : smallSize } ) ;
78+ // Synchronously interrupt the pipe before it can read EOF.
79+ stream . destroy ( ) ;
7780 } ) ) ;
7881
7982 // Compat 'finish' must not fire on aborted pipe either.
@@ -87,17 +90,11 @@ function testPeerAbort() {
8790 const client = http2 . connect ( `http://localhost:${ server . address ( ) . port } ` ) ;
8891 const req = client . request ( ) ;
8992 req . on ( 'error' , ( ) => { } ) ;
90- // Don't consume data - once response headers arrive, RST. The
91- // initial flow-control window means the server's pipe will have
92- // read at most ~64 KiB of the 1 MiB file, so EOF won't be reached.
93- req . on ( 'response' , common . mustCall ( ( ) => {
94- setImmediate ( ( ) => req . close ( NGHTTP2_CANCEL ) ) ;
95- } ) ) ;
9693 req . on ( 'close' , common . mustCall ( ( ) => {
9794 client . close ( ) ;
9895 server . close ( ) ;
9996 } ) ) ;
10097 } ) ) ;
10198}
10299
103- testCleanCompletion ( testPeerAbort ) ;
100+ testCleanCompletion ( testAbortBeforeCompletion ) ;
0 commit comments