Skip to content

Commit e08ad47

Browse files
committed
Consolidate datagram socket shutdown tests
1 parent 719684a commit e08ad47

1 file changed

Lines changed: 47 additions & 75 deletions

File tree

packages/effect/test/unstable/socket/DatagramSocket.test.ts

Lines changed: 47 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)