@@ -125,18 +125,6 @@ describe("DatagramSocket.fromTransport", () => {
125125 assert . deepStrictEqual ( yield * socket . reader . pull , [ packet ( [ 2 ] ) ] )
126126 } ) )
127127
128- it . effect ( "discards packets when closed before a notified reader resumes" , ( ) =>
129- Effect . gen ( function * ( ) {
130- const scope = yield * Scope . fork ( yield * Effect . scope )
131- const { handlers, socket } = yield * transportFixture ( ) . pipe ( Scope . provide ( scope ) )
132- const waiting = yield * socket . reader . pull . pipe ( Effect . flip , Effect . forkChild ( { startImmediately : true } ) )
133- handlers . onMessage ( new Uint8Array ( [ 1 ] ) , address )
134- handlers . onMessage ( new Uint8Array ( [ 2 ] ) , address )
135- yield * Scope . close ( scope , Exit . void )
136- assert . strictEqual ( ( yield * Fiber . join ( waiting ) ) . reason . _tag , "DatagramSocketClosedError" )
137- assert . strictEqual ( ( yield * Effect . flip ( socket . reader . pull ) ) . reason . _tag , "DatagramSocketClosedError" )
138- } ) )
139-
140128 it . effect ( "fails all readers with the first receive error until the socket closes" , ( ) =>
141129 Effect . gen ( function * ( ) {
142130 const scope = yield * Scope . fork ( yield * Effect . scope )
@@ -221,68 +209,52 @@ describe("DatagramSocket.fromTransport", () => {
221209 assert . isTrue ( released )
222210 } ) )
223211
224- it . effect ( "settles pending acquisition before waiting for transport cleanup" , ( ) =>
225- Effect . gen ( function * ( ) {
226- const scope = yield * Scope . fork ( yield * Effect . scope )
227- const acquiring = yield * Deferred . make < void > ( )
228- const interrupted = yield * Deferred . make < void > ( )
229- const cleanupStarted = yield * Deferred . make < void > ( )
230- const finishCleanup = yield * Deferred . make < void > ( )
231- const opening = yield * Datagram . fromTransport ( { localAddress : address } , ( ) =>
232- Effect . gen ( function * ( ) {
233- yield * Effect . addFinalizer ( ( ) =>
234- Deferred . succeed ( cleanupStarted , undefined ) . pipe ( Effect . andThen ( Deferred . await ( finishCleanup ) ) )
235- )
236- yield * Deferred . succeed ( acquiring , undefined )
237- return yield * Effect . never . pipe ( Effect . onInterrupt ( ( ) => Deferred . succeed ( interrupted , undefined ) ) )
238- } ) ) . pipe ( Scope . provide ( scope ) , Effect . flip , Effect . forkChild )
239- yield * Deferred . await ( acquiring )
240- const closing = yield * Scope . close ( scope , Exit . void ) . pipe ( Effect . forkChild )
241- yield * Effect . gen ( function * ( ) {
242- yield * Deferred . await ( cleanupStarted )
243- yield * Deferred . await ( interrupted )
244- assert . strictEqual ( ( yield * Fiber . join ( opening ) ) . reason . _tag , "DatagramSocketClosedError" )
245- } ) . pipe ( Effect . ensuring ( Deferred . succeed ( finishCleanup , undefined ) ) )
246- yield * Fiber . join ( closing )
247- } ) )
248-
249- it . effect ( "settles reads and sends before waiting for transport cleanup" , ( ) =>
250- Effect . gen ( function * ( ) {
251- const scope = yield * Scope . fork ( yield * Effect . scope )
252- const sendStarted = yield * Deferred . make < void > ( )
253- const sendInterrupted = yield * Deferred . make < void > ( )
254- const cleanupStarted = yield * Deferred . make < void > ( )
255- const finishCleanup = yield * Deferred . make < void > ( )
256- let handlers ! : Datagram . Handlers
257- const socket = yield * Datagram . fromTransport ( { localAddress : address } , ( callbacks ) =>
258- Effect . gen ( function * ( ) {
259- handlers = callbacks
260- yield * Effect . addFinalizer ( ( ) =>
261- Deferred . succeed ( cleanupStarted , undefined ) . pipe ( Effect . andThen ( Deferred . await ( finishCleanup ) ) )
262- )
263- return {
264- address,
265- send : ( ) =>
266- Deferred . succeed ( sendStarted , undefined ) . pipe (
267- Effect . andThen ( Effect . never ) ,
268- Effect . onInterrupt ( ( ) => Deferred . succeed ( sendInterrupted , undefined ) )
269- )
270- }
271- } ) ) . pipe ( Scope . provide ( scope ) )
272- const reading = yield * socket . reader . pull . pipe ( Effect . flip , Effect . forkChild ( { startImmediately : true } ) )
273- const sending = yield * socket . writer . write ( outgoing ) . pipe ( Effect . flip , Effect . forkChild )
274- yield * Deferred . await ( sendStarted )
275- const closing = yield * Scope . close ( scope , Exit . void ) . pipe ( Effect . forkChild )
276- yield * Effect . gen ( function * ( ) {
277- yield * Deferred . await ( cleanupStarted )
278- yield * Deferred . await ( sendInterrupted )
279- assert . strictEqual ( ( yield * Fiber . join ( reading ) ) . reason . _tag , "DatagramSocketClosedError" )
280- assert . strictEqual ( ( yield * Fiber . join ( sending ) ) . reason . _tag , "DatagramSocketClosedError" )
212+ it . effect . each ( [ "acquisition" , "I/O" ] as const ) (
213+ "settles pending %s before transport cleanup finishes" ,
214+ ( phase ) =>
215+ Effect . gen ( function * ( ) {
216+ const scope = yield * Scope . fork ( yield * Effect . scope )
217+ const started = yield * Deferred . make < void > ( )
218+ const interrupted = yield * Deferred . make < void > ( )
219+ const cleanupStarted = yield * Deferred . make < void > ( )
220+ const finishCleanup = yield * Deferred . make < void > ( )
221+ const pending = Deferred . succeed ( started , undefined ) . pipe (
222+ Effect . andThen ( Effect . never ) ,
223+ Effect . onInterrupt ( ( ) => Deferred . succeed ( interrupted , undefined ) )
224+ )
225+ let handlers ! : Datagram . Handlers
226+ const acquire = Datagram . fromTransport ( { localAddress : address } , ( callbacks ) =>
227+ Effect . gen ( function * ( ) {
228+ handlers = callbacks
229+ yield * Effect . addFinalizer ( ( ) =>
230+ Deferred . succeed ( cleanupStarted , undefined ) . pipe ( Effect . andThen ( Deferred . await ( finishCleanup ) ) )
231+ )
232+ if ( phase === "acquisition" ) return yield * pending
233+ return { address, send : ( ) => pending }
234+ } ) ) . pipe ( Scope . provide ( scope ) )
235+ const operations = phase === "acquisition"
236+ ? [ Effect . asVoid ( acquire ) ]
237+ : yield * Effect . map ( acquire , ( socket ) => [ Effect . asVoid ( socket . reader . pull ) , socket . writer . write ( outgoing ) ] )
238+ const fibers = yield * Effect . forEach ( operations , ( operation ) =>
239+ operation . pipe ( Effect . flip , Effect . forkChild ( { startImmediately : true } ) ) )
240+ yield * Deferred . await ( started )
241+ // Closing must discard packets even if a reader was just notified.
281242 handlers . onMessage ( new Uint8Array ( [ 1 ] ) , address )
282- handlers . onError ( "late error" )
283- assert . strictEqual ( ( yield * Effect . flip ( socket . reader . pull ) ) . reason . _tag , "DatagramSocketClosedError" )
284- assert . strictEqual ( ( yield * Effect . flip ( socket . writer . write ( outgoing ) ) ) . reason . _tag , "DatagramSocketClosedError" )
285- } ) . pipe ( Effect . ensuring ( Deferred . succeed ( finishCleanup , undefined ) ) )
286- yield * Fiber . join ( closing )
287- } ) )
243+ handlers . onMessage ( new Uint8Array ( [ 2 ] ) , address )
244+ const closing = yield * Scope . close ( scope , Exit . void ) . pipe ( Effect . forkChild ( { startImmediately : true } ) )
245+ yield * Effect . gen ( function * ( ) {
246+ yield * Deferred . await ( cleanupStarted )
247+ yield * Deferred . await ( interrupted )
248+ for ( const fiber of fibers ) {
249+ assert . strictEqual ( ( yield * Fiber . join ( fiber ) ) . reason . _tag , "DatagramSocketClosedError" )
250+ }
251+ handlers . onMessage ( new Uint8Array ( [ 3 ] ) , address )
252+ handlers . onError ( "late error" )
253+ for ( const operation of operations ) {
254+ assert . strictEqual ( ( yield * Effect . flip ( operation ) ) . reason . _tag , "DatagramSocketClosedError" )
255+ }
256+ } ) . pipe ( Effect . ensuring ( Deferred . succeed ( finishCleanup , undefined ) ) )
257+ yield * Fiber . join ( closing )
258+ } )
259+ )
288260} )
0 commit comments