Files
deepseek-harness/packages/host/directory-picker-native/tests/win32-dialog-logic.spec.ts
Huanqi Cao 020ce50414 fix(picker): correct crash-isolation and DPI claims, wire the built-worker guard, and tidy round-four nits
The round-four review's v6 pass found three factual gaps and the v5 pass two
nits. Correct them before merge:

- The in-process note claimed a koffi signature mistake is 'contained to
  the worker thread' — worker_threads share the process, so a native access
  violation takes down the whole Node process with no PowerShell fallback.
  State the real blast radius and record the deferred pkg-VFS worker-spawn
  arm in Consequences (both languages, pairing re-recorded).
- The 2026-07-27 picker note claimed unconditional 'per-monitor-v2 DPI';
  PMv2-less hosts (Server 2016 / Win10 1607) cascade to per-monitor or
  system-aware. Say 'the best thread DPI awareness the host accepts'
  (both languages, pairing re-recorded).
- built-worker.e2e.ts was not in any keyless gate (vitest.e2e config is
  not part of the default unit run and builtBinSmokeGate's explicit list
  missed it), so lib/worker.cjs load regressions passed keyless CI. Add it
  to builtBinSmokeGate alongside the workflow-workerthread sibling.
- Remove the dead trailing 'void bindings' in win32-dialog-logic.spec.ts
  and give native-picker.spec.ts the sibling module header it lacked.
2026-08-05 00:31:43 +08:00

99 lines
4.1 KiB
TypeScript

/**
* The COM conversation's sequencing against fake bindings: outcome mapping
* (selection / cancellation / HRESULT failures at every step) and the
* release-on-every-path guarantee, all platform-independent.
*/
import { describe, expect, it, vi } from 'vitest'
import {
FOS_FORCEFILESYSTEM, FOS_NOCHANGEDIR, FOS_PICKFOLDERS, HRESULT_CANCELLED,
runFolderDialog, type Win32DialogBindings, type Win32FolderDialog,
} from '../src/win32-dialog-logic.ts'
const E_FAIL = 0x80004005 | 0
interface FakeWorld {
bindings: Win32DialogBindings
dpi: ReturnType<typeof vi.fn>
createDialog: ReturnType<typeof vi.fn>
uninitialize: ReturnType<typeof vi.fn>
dialog: {
setOptions: ReturnType<typeof vi.fn>
setTitle: ReturnType<typeof vi.fn>
show: ReturnType<typeof vi.fn>
resultPath: ReturnType<typeof vi.fn>
release: ReturnType<typeof vi.fn>
}
}
function world(overrides: Partial<Win32FolderDialog> = {}, coInit = 0): FakeWorld {
const dialog = {
setOptions: vi.fn(() => 0),
setTitle: vi.fn(() => 0),
show: vi.fn(() => 0),
resultPath: vi.fn(() => ({ hr: 0, path: 'C:\\picked\\目录' })),
release: vi.fn(),
...overrides,
}
const dpi = vi.fn()
const createDialog = vi.fn(() => dialog)
const uninitialize = vi.fn()
const bindings: Win32DialogBindings = {
setThreadDpiAwareness: dpi,
coInitializeSta: vi.fn(() => coInit),
coUninitialize: uninitialize,
createFolderDialog: createDialog,
currentThreadId: vi.fn(() => 4242),
}
return { bindings, dpi, createDialog, uninitialize, dialog: dialog as FakeWorld['dialog'] }
}
describe('runFolderDialog', () => {
it('sequences DPI, STA, options, title, show, result extraction, and apartment teardown', () => {
const { bindings, dpi, dialog, uninitialize } = world()
const showing = vi.fn()
expect(runFolderDialog(bindings, 'Pick', showing)).toBe('C:\\picked\\目录')
expect(dpi).toHaveBeenCalledOnce()
expect(uninitialize).toHaveBeenCalledOnce()
expect(dialog.release.mock.invocationCallOrder[0]).toBeLessThan(uninitialize.mock.invocationCallOrder[0] as number)
expect(dialog.setOptions).toHaveBeenCalledWith(FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM | FOS_NOCHANGEDIR)
expect(dialog.setTitle).toHaveBeenCalledWith('Pick')
expect(showing).toHaveBeenCalledWith(4242)
expect(showing.mock.invocationCallOrder[0]).toBeLessThan(dialog.show.mock.invocationCallOrder[0] as number)
expect(dialog.release).toHaveBeenCalledOnce()
})
it('maps the cancelled HRESULT to null and still releases the dialog and apartment', () => {
const { bindings, dialog, uninitialize } = world({ show: vi.fn(() => HRESULT_CANCELLED) })
expect(runFolderDialog(bindings, 'Pick', vi.fn())).toBeNull()
expect(dialog.resultPath).not.toHaveBeenCalled()
expect(dialog.release).toHaveBeenCalledOnce()
expect(uninitialize).toHaveBeenCalledOnce()
})
it('accepts the S_FALSE re-entry HRESULT from CoInitializeEx', () => {
const { bindings } = world({}, 1)
expect(runFolderDialog(bindings, 'Pick', vi.fn())).toBe('C:\\picked\\目录')
})
it('throws on a failing CoInitializeEx without creating a dialog or uninitializing', () => {
const { bindings, createDialog, uninitialize } = world({}, E_FAIL)
expect(() => runFolderDialog(bindings, 'Pick', vi.fn())).toThrow('CoInitializeEx failed: HRESULT 0x80004005')
expect(createDialog).not.toHaveBeenCalled()
// A failed CoInitializeEx must NOT be paired with CoUninitialize.
expect(uninitialize).not.toHaveBeenCalled()
})
it.each([
['SetOptions', { setOptions: vi.fn(() => E_FAIL) }],
['SetTitle', { setTitle: vi.fn(() => E_FAIL) }],
['Show', { show: vi.fn(() => E_FAIL) }],
['GetResult', { resultPath: vi.fn(() => ({ hr: E_FAIL })) }],
] satisfies [string, Partial<Win32FolderDialog>][])('releases the dialog and apartment when %s fails', (what, overrides) => {
const { bindings, dialog, uninitialize } = world(overrides)
expect(() => runFolderDialog(bindings, 'Pick', vi.fn())).toThrow(`${what} failed: HRESULT 0x80004005`)
expect(dialog.release).toHaveBeenCalledOnce()
expect(uninitialize).toHaveBeenCalledOnce()
})
})