72 lines
2.8 KiB
TypeScript
72 lines
2.8 KiB
TypeScript
// tests/main/shutdown-registry.test.ts
|
|
// 종료 등록부 — 역순 정리, 멱등, 멈춘 항목이 종료를 막지 않음.
|
|
|
|
import { describe, it, expect, vi } from 'vitest'
|
|
import { ShutdownRegistry } from '../../src/main/shutdown-registry'
|
|
|
|
describe('ShutdownRegistry', () => {
|
|
it('등록의 역순으로 정리한다', async () => {
|
|
const order: string[] = []
|
|
const registry = new ShutdownRegistry()
|
|
registry.register({ name: 'a', dispose: () => { order.push('a') } })
|
|
registry.register({ name: 'b', dispose: async () => { order.push('b') } })
|
|
registry.register({ name: 'c', dispose: () => { order.push('c') } })
|
|
|
|
const report = await registry.disposeAll(1000)
|
|
expect(order).toEqual(['c', 'b', 'a'])
|
|
expect(report.completed).toEqual(['c', 'b', 'a'])
|
|
})
|
|
|
|
it('여러 번 불러도 한 번만 정리한다', async () => {
|
|
const dispose = vi.fn()
|
|
const registry = new ShutdownRegistry()
|
|
registry.register({ name: 'x', dispose })
|
|
await Promise.all([registry.disposeAll(1000), registry.disposeAll(1000)])
|
|
await registry.disposeAll(1000)
|
|
expect(dispose).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('실패한 항목은 기록하고 나머지를 계속 정리한다', async () => {
|
|
const onError = vi.fn()
|
|
const later = vi.fn()
|
|
const registry = new ShutdownRegistry({ onError })
|
|
registry.register({ name: 'later', dispose: later })
|
|
registry.register({ name: 'throws', dispose: () => { throw new Error('sync boom') } })
|
|
registry.register({ name: 'rejects', dispose: async () => { throw new Error('async boom') } })
|
|
|
|
const report = await registry.disposeAll(1000)
|
|
expect(report.failed).toEqual(['rejects', 'throws'])
|
|
expect(report.completed).toEqual(['later'])
|
|
expect(later).toHaveBeenCalledTimes(1)
|
|
expect(onError).toHaveBeenCalledTimes(2)
|
|
})
|
|
|
|
it('멈춘 항목이 있어도 상한 시간 안에 끝나고, 남은 항목의 dispose 는 걸어 둔다', async () => {
|
|
vi.useFakeTimers()
|
|
try {
|
|
const last = vi.fn()
|
|
const registry = new ShutdownRegistry()
|
|
registry.register({ name: 'last', dispose: last })
|
|
registry.register({ name: 'hangs', dispose: () => new Promise<void>(() => undefined) })
|
|
|
|
const running = registry.disposeAll(500)
|
|
await vi.advanceTimersByTimeAsync(501)
|
|
const report = await running
|
|
|
|
expect(report.timedOut).toEqual(['hangs', 'last'])
|
|
// 기다리진 않지만 동기 구간(프로세스 kill 등)은 실행된다
|
|
expect(last).toHaveBeenCalledTimes(1)
|
|
} finally {
|
|
vi.useRealTimers()
|
|
}
|
|
})
|
|
|
|
it('등록 취소한 항목은 정리하지 않는다', async () => {
|
|
const dispose = vi.fn()
|
|
const registry = new ShutdownRegistry()
|
|
const unregister = registry.register({ name: 'x', dispose })
|
|
unregister()
|
|
await registry.disposeAll(1000)
|
|
expect(dispose).not.toHaveBeenCalled()
|
|
})
|
|
})
|