@@ -1313,6 +1313,8 @@ describe(QUICStream.name, () => {
13131313 } ) ( ) ,
13141314 ) ;
13151315 }
1316+ // Yield to allow streams to propagate
1317+ await sleep ( 0 ) ;
13161318
13171319 // Start unforced close of client
13181320 const clientDestroyP = client . destroy ( { force : false } ) ;
@@ -1402,6 +1404,8 @@ describe(QUICStream.name, () => {
14021404 } ) ( ) ,
14031405 ) ;
14041406 }
1407+ // Yield to allow streams to propagate
1408+ await sleep ( 0 ) ;
14051409
14061410 // Start unforced close of server
14071411 const serverStopP = server . stop ( { force : false } ) ;
@@ -1489,7 +1493,87 @@ describe(QUICStream.name, () => {
14891493 await expect ( asd ) . rejects . toThrow ( 'read 1' ) ;
14901494
14911495 waitResolveP ( ) ;
1496+ await Promise . all ( activeServerStreams ) ;
1497+ await clientDestroyP ;
1498+ await server . stop ( { force : true } ) ;
1499+ } ) ;
1500+ test ( 'connection can be forced closed after unforced destroy' , async ( ) => {
1501+ const message = Buffer . from ( 'The Quick Brown Fox Jumped Over The Lazy Dog' ) ;
1502+ const connectionEventProm =
1503+ utils . promise < events . EventQUICServerConnection > ( ) ;
1504+ const tlsConfig = await generateTLSConfig ( defaultType ) ;
1505+ const server = new QUICServer ( {
1506+ crypto : {
1507+ key,
1508+ ops : serverCrypto ,
1509+ } ,
1510+ logger : logger . getChild ( QUICServer . name ) ,
1511+ config : {
1512+ key : tlsConfig . leafKeyPairPEM . privateKey ,
1513+ cert : tlsConfig . leafCertPEM ,
1514+ verifyPeer : false ,
1515+ } ,
1516+ } ) ;
1517+ socketCleanMethods . extractSocket ( server ) ;
1518+ server . addEventListener (
1519+ events . EventQUICServerConnection . name ,
1520+ ( e : events . EventQUICServerConnection ) => connectionEventProm . resolveP ( e ) ,
1521+ ) ;
1522+ await server . start ( {
1523+ host : localhost ,
1524+ } ) ;
1525+ const client = await QUICClient . createQUICClient ( {
1526+ host : localhost ,
1527+ port : server . port ,
1528+ localHost : localhost ,
1529+ crypto : {
1530+ ops : clientCrypto ,
1531+ } ,
1532+ logger : logger . getChild ( QUICClient . name ) ,
1533+ config : {
1534+ verifyPeer : false ,
1535+ } ,
1536+ } ) ;
1537+ socketCleanMethods . extractSocket ( client ) ;
1538+ const conn = ( await connectionEventProm . p ) . detail ;
1539+
1540+ // Do the test
1541+ const { p : waitP , resolveP : waitResolveP } = utils . promise ( ) ;
1542+ const activeServerStreams : Array < Promise < void > > = [ ] ;
1543+ conn . addEventListener (
1544+ events . EventQUICConnectionStream . name ,
1545+ async ( streamEvent : events . EventQUICConnectionStream ) => {
1546+ const stream = streamEvent . detail ;
1547+ await waitP ;
1548+ const streamProm = stream . readable
1549+ . pipeTo ( stream . writable )
1550+ . catch ( ( ) => { } ) ;
1551+ activeServerStreams . push ( streamProm ) ;
1552+ } ,
1553+ ) ;
1554+
1555+ const stream = client . connection . newStream ( ) ;
1556+ const writer = stream . writable . getWriter ( ) ;
1557+ await writer . write ( message ) ;
1558+ await writer . close ( ) ;
1559+
1560+ // Start unforced close of client
1561+ const clientDestroyP = client . destroy ( { force : false } ) ;
1562+
1563+ const result = await Promise . race ( [
1564+ clientDestroyP . then ( ( ) => true ) ,
1565+ sleep ( 500 ) . then ( ( ) => false ) ,
1566+ ] ) ;
1567+
1568+ expect ( result ) . toBe ( false ) ;
1569+
1570+ // We can force close the streams causing client destruction to end
1571+ client . connection . destroyStreams ( ) ;
14921572 await clientDestroyP ;
1573+ await Promise . allSettled ( activeServerStreams ) ;
1574+
14931575 await server . stop ( { force : true } ) ;
1576+ waitResolveP ( ) ;
1577+ await waitP ;
14941578 } ) ;
14951579} ) ;
0 commit comments