Files
deepseek-harness/packages/support/invariants/tests/service.spec.ts
2026-07-20 00:38:37 +08:00

487 lines
18 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import { Context, Service } from 'cordis'
import InvariantService, {
InvariantError,
assertInvariant,
observePluginInvariant,
observeServiceInvariant,
serviceShapeViolation,
type Config,
type InvariantInstaller,
type PluginInvariantContract,
} from '@deepseek-ai/dsh-invariants'
declare module 'cordis' {
interface Context {
invariantProbe: InvariantProbeService
watchedInvariantProbe: WatchedInvariantProbeService
}
interface Events {
'invariants-test/ping'(): void
}
}
class InvariantProbeService extends Service {
constructor(ctx: Context) {
super(ctx, 'invariantProbe')
}
}
class WatchedInvariantProbeService extends Service {
constructor(ctx: Context) {
super(ctx, 'watchedInvariantProbe')
}
}
interface RuntimeRegistration extends PromiseLike<() => void> {
(): void | Promise<void>
}
interface InstalledRegistration {
dispose(): Promise<void>
}
function runtimeRegistration(registration: () => void): RuntimeRegistration {
return registration as RuntimeRegistration
}
async function setup(config: Config = {}): Promise<{ ctx: Context; fiber: Awaited<ReturnType<Context['plugin']>> }> {
const ctx = new Context()
const fiber = await ctx.plugin(InvariantService, config)
return { ctx, fiber }
}
async function registerProbe(
ctx: Context,
packageName: string,
probe: () => void,
): Promise<InstalledRegistration> {
const registration = runtimeRegistration(ctx.invariants.register(packageName, (child) => {
child.on('invariants-test/ping', probe, { global: true })
}))
await registration
return {
async dispose() { await registration() },
}
}
describe('InvariantService selection', () => {
it('applies defaults when constructed directly without schema normalization', async () => {
const ctx = new Context()
const service = new InvariantService(ctx)
const probe = vi.fn()
const registration = runtimeRegistration(service.register('@deepseek-ai/dsh-session', (child) => {
child.on('invariants-test/ping', probe, { global: true })
}))
await registration
ctx.emit('invariants-test/ping')
expect(probe).toHaveBeenCalledOnce()
await registration()
})
it('enables registrations by default and treats empty lists as admit-all and exclude-none', async () => {
for (const config of [{}, { package_allowlist: [], package_blocklist: [] }]) {
const { ctx } = await setup(config)
const probe = vi.fn()
await registerProbe(ctx, '@deepseek-ai/dsh-session', probe)
ctx.emit('invariants-test/ping')
expect(probe).toHaveBeenCalledOnce()
}
})
it('disables every installer while still reserving package ownership', async () => {
const { ctx } = await setup({ enabled: false })
const probe = vi.fn()
const registration = await registerProbe(ctx, '@deepseek-ai/dsh-session', probe)
expect(() => ctx.invariants.register('@deepseek-ai/dsh-session', () => {}))
.toThrow(/already registered/)
ctx.emit('invariants-test/ping')
expect(probe).not.toHaveBeenCalled()
await registration.dispose()
})
it('uses unanchored, case-sensitive JavaScript regex sources', async () => {
const unanchored = await setup({ package_allowlist: ['session'] })
const unanchoredProbe = vi.fn()
await registerProbe(unanchored.ctx, '@deepseek-ai/dsh-session-extra', unanchoredProbe)
unanchored.ctx.emit('invariants-test/ping')
expect(unanchoredProbe).toHaveBeenCalledOnce()
const anchored = await setup({ package_allowlist: ['^@deepseek-ai/dsh-session$'] })
const anchoredProbe = vi.fn()
await registerProbe(anchored.ctx, '@deepseek-ai/dsh-session-extra', anchoredProbe)
anchored.ctx.emit('invariants-test/ping')
expect(anchoredProbe).not.toHaveBeenCalled()
const caseSensitive = await setup({ package_allowlist: ['Session'] })
const caseProbe = vi.fn()
await registerProbe(caseSensitive.ctx, '@deepseek-ai/dsh-session', caseProbe)
caseSensitive.ctx.emit('invariants-test/ping')
expect(caseProbe).not.toHaveBeenCalled()
})
it('lets the blocklist override an allowlist match', async () => {
const { ctx } = await setup({
package_allowlist: ['^@deepseek-ai/dsh-'],
package_blocklist: ['session'],
})
const sessionProbe = vi.fn()
const agentProbe = vi.fn()
await registerProbe(ctx, '@deepseek-ai/dsh-session', sessionProbe)
await registerProbe(ctx, '@deepseek-ai/dsh-agent', agentProbe)
ctx.emit('invariants-test/ping')
expect(sessionProbe).not.toHaveBeenCalled()
expect(agentProbe).toHaveBeenCalledOnce()
})
it('accepts zero-match patterns for packages registered later', async () => {
const { ctx } = await setup({ package_allowlist: ['^@later/invariants$'] })
const now = vi.fn()
const later = vi.fn()
await registerProbe(ctx, '@deepseek-ai/dsh-session', now)
await registerProbe(ctx, '@later/invariants', later)
ctx.emit('invariants-test/ping')
expect(now).not.toHaveBeenCalled()
expect(later).toHaveBeenCalledOnce()
})
it('allows the same source in both lists and applies blocklist precedence', async () => {
const { ctx } = await setup({ package_allowlist: ['agent'], package_blocklist: ['agent'] })
const probe = vi.fn()
await registerProbe(ctx, '@deepseek-ai/dsh-agent', probe)
ctx.emit('invariants-test/ping')
expect(probe).not.toHaveBeenCalled()
})
})
describe('InvariantService validation', () => {
it.each([
[{ package_allowlist: [''] }, /non-blank/],
[{ package_allowlist: [' '] }, /non-blank/],
[{ package_allowlist: [' session'] }, /surrounding whitespace/],
[{ package_blocklist: ['session '] }, /surrounding whitespace/],
[{ package_allowlist: ['session', 'session'] }, /duplicate regex/],
[{ package_blocklist: ['agent', 'agent'] }, /duplicate regex/],
[{ package_allowlist: ['['] }, /invalid regex/],
[{ package_blocklist: ['('] }, /invalid regex/],
])('rejects malformed filter config %#', async (config, message) => {
await expect((async () => {
const ctx = new Context()
await ctx.plugin(InvariantService, config)
})()).rejects.toThrow(message)
})
it.each(['', ' ', ' package', 'pack age', 'package\n'])('rejects malformed package name %j', async (packageName) => {
const { ctx } = await setup()
expect(() => ctx.invariants.register(packageName, () => {})).toThrow(/packageName/)
})
})
describe('InvariantService lifecycle', () => {
it('honors the installer dependency surface in its child fiber', async () => {
const { ctx } = await setup()
await ctx.plugin(InvariantProbeService)
let registration!: RuntimeRegistration
await ctx.plugin({
inject: ['invariants', 'invariantProbe'],
apply(child: Context) {
const installer = Object.assign((installerCtx: Context) => {
expect(Object.keys(installerCtx.fiber.inject)).toContain('invariantProbe')
expect(Object.keys(installerCtx.fiber.store ?? {})).toContain('invariantProbe')
expect(installerCtx.invariantProbe).toBeInstanceOf(InvariantProbeService)
}, { inject: ['invariantProbe'] })
expect(installer.inject).toEqual(['invariantProbe'])
registration = runtimeRegistration(child.invariants.register('@deepseek-ai/dsh-probe', installer))
return Promise.resolve(registration)
},
})
await registration
})
it('attributes failures to the registering package with the stable code', async () => {
const { ctx } = await setup()
const registration = runtimeRegistration(ctx.invariants.register('@deepseek-ai/dsh-session', (child, fail) => {
child.on('invariants-test/ping', () => fail('seq must strictly increase'), { global: true })
}))
await registration
let caught: unknown
try {
ctx.emit('invariants-test/ping')
} catch (error) {
caught = error
}
expect(caught).toBeInstanceOf(InvariantError)
expect(caught).toMatchObject({
name: 'InvariantError',
code: 'INVARIANT',
packageName: '@deepseek-ai/dsh-session',
message: 'invariant violated by "@deepseek-ai/dsh-session": seq must strictly increase',
})
})
it('disposes the child fiber completely and permits HMR re-registration', async () => {
const { ctx } = await setup()
const first = vi.fn()
const firstRegistration = await registerProbe(ctx, '@deepseek-ai/dsh-session', first)
ctx.emit('invariants-test/ping')
await firstRegistration.dispose()
ctx.emit('invariants-test/ping')
expect(first).toHaveBeenCalledOnce()
const second = vi.fn()
await registerProbe(ctx, '@deepseek-ai/dsh-session', second)
ctx.emit('invariants-test/ping')
expect(first).toHaveBeenCalledOnce()
expect(second).toHaveBeenCalledOnce()
})
it('reserves ownership until asynchronous child disposal completes', async () => {
const { ctx } = await setup()
let finishDisposal!: () => void
const disposalBarrier = new Promise<void>((resolve) => { finishDisposal = resolve })
const registration = runtimeRegistration(ctx.invariants.register('@deepseek-ai/dsh-session', (child) => {
child.effect(() => async () => { await disposalBarrier })
}))
await registration
const disposing = registration()
expect(() => ctx.invariants.register('@deepseek-ai/dsh-session', () => {}))
.toThrow(/already registered/)
finishDisposal()
await disposing
const replacement = runtimeRegistration(ctx.invariants.register('@deepseek-ai/dsh-session', () => {}))
await replacement
await replacement()
})
it('rolls back listeners and ownership atomically when an installer fails', async () => {
const { ctx } = await setup()
const leaked = vi.fn()
const failed = runtimeRegistration(ctx.invariants.register('@deepseek-ai/dsh-session', (child) => {
child.on('invariants-test/ping', leaked, { global: true })
throw new Error('installer failed')
}))
await expect(Promise.resolve(failed)).rejects.toThrow('installer failed')
ctx.emit('invariants-test/ping')
expect(leaked).not.toHaveBeenCalled()
const retry = vi.fn()
await registerProbe(ctx, '@deepseek-ai/dsh-session', retry)
ctx.emit('invariants-test/ping')
expect(retry).toHaveBeenCalledOnce()
})
it('releases a synchronous reservation if the service fiber is already inactive', async () => {
const { ctx, fiber } = await setup()
const service = ctx.invariants
await fiber.dispose()
expect(() => service.register('@deepseek-ai/dsh-session', () => {})).toThrow(/inactive/i)
})
})
describe('package-owned invariant helpers', () => {
async function registerInstaller(
ctx: Context,
packageName: string,
installer: InvariantInstaller,
): Promise<() => void> {
const registration = runtimeRegistration(ctx.invariants.register(packageName, installer))
const dispose = await Promise.resolve(registration)
return dispose
}
function effectPlugin(options: {
name?: string
inject?: string[]
effect?: string
service?: string
} = {}) {
return {
name: options.name ?? 'effect-probe',
inject: options.inject ?? [],
apply(ctx: Context) {
if (options.service !== undefined) ctx.provide(options.service, {})
if (options.effect !== undefined) {
ctx.effect(() => {
ctx.effect(() => () => {}, `${options.effect}.child`)
return () => {}
}, options.effect)
}
},
}
}
async function expectPluginViolation(
contract: PluginInvariantContract,
plugin: ReturnType<typeof effectPlugin>,
message: RegExp,
): Promise<void> {
const { ctx } = await setup()
await registerInstaller(ctx, `@deepseek-ai/${contract.name}`, (child, fail) => {
observePluginInvariant(child, fail, contract)
})
await expect(Promise.resolve(ctx.plugin(plugin))).rejects.toThrow(message)
}
it('checks existing and later plugin fibers, including nested effects and alternatives', async () => {
const { ctx } = await setup()
await ctx.plugin(InvariantProbeService)
const plugin = effectPlugin({
inject: ['invariantProbe'],
effect: 'probe.effect',
service: 'pluginProbe',
})
await ctx.plugin(plugin)
const validated = vi.fn(() => undefined)
await registerInstaller(ctx, '@deepseek-ai/dsh-existing-probe', (child, fail) => {
observePluginInvariant(child, fail, {
plugin,
name: 'effect-probe',
inject: ['invariantProbe'],
effects: [['missing.effect', 'probe.effect.child']],
services: ['pluginProbe'],
validate: validated,
})
})
expect(validated).toHaveBeenCalledOnce()
const later = effectPlugin({ name: 'later-probe', effect: 'later.effect' })
await registerInstaller(ctx, '@deepseek-ai/dsh-later-probe', (child, fail) => {
observePluginInvariant(child, fail, {
plugin: later,
name: 'later-probe',
effects: ['later.effect'],
})
})
await ctx.plugin(later)
})
it('matches package plugins by Cordis name without importing their callback', async () => {
const { ctx } = await setup()
const plugin = {
name: 'name-only-probe',
apply(pluginCtx: Context) {
pluginCtx.effect(() => () => {}, 'name-only.effect')
pluginCtx.inject([], () => {})
},
}
await registerInstaller(ctx, '@deepseek-ai/dsh-name-only-probe', (child, fail) => {
observePluginInvariant(child, fail, {
name: 'name-only-probe',
effects: ['name-only.effect'],
})
})
await ctx.plugin(plugin)
})
it('rejects a contract that does not identify a plugin', async () => {
const { ctx } = await setup()
const registration = runtimeRegistration(ctx.invariants.register('@deepseek-ai/dsh-invalid-plugin', (child, fail) => {
observePluginInvariant(child, fail, {
plugin: {} as never,
name: 'invalid-plugin',
})
}))
await expect(Promise.resolve(registration)).rejects.toThrow(/does not identify a Cordis plugin/)
})
it('rejects wrong plugin names, missing injections, effects, services, and custom checks', async () => {
const wrongName = effectPlugin({ name: 'actual-name', effect: 'probe.effect' })
await expectPluginViolation({
plugin: wrongName,
name: 'expected-name',
}, wrongName, /plugin name must be "expected-name"/)
const missingInjection = effectPlugin({ effect: 'probe.effect' })
await expectPluginViolation({
plugin: missingInjection,
name: 'effect-probe',
inject: ['missingService'],
}, missingInjection, /must inject "missingService"/)
const missingEffect = effectPlugin()
await expectPluginViolation({
plugin: missingEffect,
name: 'effect-probe',
effects: [['first.effect', 'second.effect']],
}, missingEffect, /must own effect "first.effect" or "second.effect"/)
const missingService = effectPlugin({ effect: 'probe.effect' })
await expectPluginViolation({
plugin: missingService,
name: 'effect-probe',
services: ['missingService'],
}, missingService, /must provide service "missingService"/)
const invalidCustom = effectPlugin({ effect: 'probe.effect' })
await expectPluginViolation({
plugin: invalidCustom,
name: 'effect-probe',
validate: () => 'custom plugin contract failed',
}, invalidCustom, /custom plugin contract failed/)
})
it('checks existing and future service implementations while ignoring unrelated changes', async () => {
const existing = await setup()
await existing.ctx.plugin(WatchedInvariantProbeService)
await registerInstaller(existing.ctx, '@deepseek-ai/dsh-existing-service', (child, fail) => {
observeServiceInvariant(child, fail, 'watchedInvariantProbe', value => (
value instanceof WatchedInvariantProbeService ? undefined : 'wrong watched service'
))
})
const future = await setup()
await registerInstaller(future.ctx, '@deepseek-ai/dsh-future-service', (child, fail) => {
observeServiceInvariant(child, fail, 'watchedInvariantProbe', value => (
value instanceof WatchedInvariantProbeService ? undefined : 'wrong watched service'
))
})
await future.ctx.plugin(InvariantProbeService)
await future.ctx.plugin(WatchedInvariantProbeService)
const invalid = await setup()
await registerInstaller(invalid.ctx, '@deepseek-ai/dsh-invalid-service', (child, fail) => {
observeServiceInvariant(child, fail, 'watchedInvariantProbe', () => 'wrong watched service')
})
await expect(Promise.resolve(invalid.ctx.plugin(WatchedInvariantProbeService)))
.rejects.toThrow(/wrong watched service/)
})
it('reports synchronous package assertions through the bound failure reporter', async () => {
const { ctx } = await setup()
const valid = await registerInstaller(ctx, '@deepseek-ai/dsh-valid-assertion', (_child, fail) => {
assertInvariant(fail, true, 'must stay true')
})
valid()
const invalid = runtimeRegistration(ctx.invariants.register('@deepseek-ai/dsh-invalid-assertion', (_child, fail) => {
assertInvariant(fail, false, 'must stay true')
}))
await expect(Promise.resolve(invalid)).rejects.toThrow(/must stay true/)
})
it('accepts structural service implementations and test doubles', () => {
expect(serviceShapeViolation({ kind: 'probe', run() {} }, {
methods: ['run'],
stringProperties: ['kind'],
})).toBeUndefined()
expect(serviceShapeViolation(Object.assign(() => {}, { run() {} }), {
methods: ['run'],
})).toBeUndefined()
})
it.each([
{ value: null, message: 'service implementation must be an object' },
{ value: 42, message: 'service implementation must be an object' },
{ value: {}, message: 'service implementation must expose method "run"' },
{ value: { run() {}, kind: '' }, message: 'service implementation must expose non-empty string "kind"' },
])('rejects invalid structural service implementations: $message', ({ value, message }) => {
expect(serviceShapeViolation(value, {
methods: ['run'],
stringProperties: ['kind'],
})).toBe(message)
})
})