| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- /**
- * Unit tests for the Windows durable namespace helper with a mocked kernel32
- * binding. The real JSONL suite exercises the helper on native Windows; these
- * tests keep the Win32 error mapping and race handling covered on every host.
- */
- import { afterEach, describe, expect, it, vi } from 'vitest'
- import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'
- import { mkdtemp, rm, writeFile } from 'node:fs/promises'
- import { tmpdir } from 'node:os'
- import { join } from 'node:path'
- const MOVEFILE_WRITE_THROUGH = 0x00000008
- const ERROR_FILE_NOT_FOUND = 2
- const ERROR_PATH_NOT_FOUND = 3
- const ERROR_ACCESS_DENIED = 5
- const ERROR_NOT_SAME_DEVICE = 17
- const ERROR_FILE_EXISTS = 80
- const ERROR_INVALID_NAME = 123
- const ERROR_ALREADY_EXISTS = 183
- type MoveFileExW = (existing: string, replacement: string, flags: number, setLastError: (code: number) => void) => number
- const roots: string[] = []
- function stripNamespace(path: string): string {
- if (path.startsWith('\\\\?\\UNC\\')) return `\\\\${path.slice('\\\\?\\UNC\\'.length)}`
- if (path.startsWith('\\\\?\\')) return path.slice('\\\\?\\'.length)
- return path
- }
- async function tempRoot(): Promise<string> {
- const dir = await mkdtemp(join(tmpdir(), 'dsh-jsonl-win32-'))
- roots.push(dir)
- return dir
- }
- async function importWithMove(moveFileExW: MoveFileExW): Promise<typeof import('../src/win32.ts')> {
- vi.resetModules()
- vi.doMock('koffi', () => {
- let lastError = 0
- const setLastError = (code: number): void => { lastError = code }
- const move: MoveFileExW = (existing, replacement, flags, setError) => {
- const ok = moveFileExW(existing, replacement, flags, setError)
- lastError = ok === 0 ? lastError : 0
- return ok
- }
- return {
- default: {
- load: () => ({
- func: (_convention: string, name: string, result: string) => {
- if (name === 'MoveFileExW') return (existing: string, replacement: string, flags: number) => {
- expect(result).toBe('int')
- const ok = move(existing, replacement, flags, setLastError)
- return ok
- }
- return () => lastError
- },
- }),
- },
- }
- })
- return import('../src/win32.ts')
- }
- async function importWithError(code: number): Promise<typeof import('../src/win32.ts')> {
- vi.resetModules()
- vi.doMock('koffi', () => ({
- default: {
- load: () => ({
- func: (_convention: string, name: string) => {
- if (name === 'MoveFileExW') return () => 0
- return () => code
- },
- }),
- },
- }))
- return import('../src/win32.ts')
- }
- async function importWithFilesystemMove(): Promise<typeof import('../src/win32.ts')> {
- return importWithMove((existing, replacement, flags, setLastError) => {
- expect(flags).toBe(MOVEFILE_WRITE_THROUGH)
- const from = stripNamespace(existing)
- const to = stripNamespace(replacement)
- if (!existsSync(from)) { setLastError(ERROR_FILE_NOT_FOUND); return 0 }
- if (existsSync(to)) { setLastError(ERROR_ALREADY_EXISTS); return 0 }
- renameSync(from, to)
- return 1
- })
- }
- afterEach(async () => {
- vi.doUnmock('koffi')
- vi.resetModules()
- for (const root of roots.splice(0)) await rm(root, { recursive: true, force: true })
- })
- describe('Windows durable namespace helpers', () => {
- it('publishes a new file with write-through MoveFileExW semantics', async () => {
- const { publishNewFileWin32 } = await importWithFilesystemMove()
- const root = await tempRoot()
- const tmp = join(root, 'log.tmp')
- const final = join(root, 'log.jsonl')
- await writeFile(tmp, 'content')
- await publishNewFileWin32(tmp, final)
- expect(existsSync(tmp)).toBe(false)
- expect(readFileSync(final, 'utf8')).toBe('content')
- })
- it('maps Win32 publish failures to Node-style errno codes', async () => {
- const cases = [
- [ERROR_FILE_NOT_FOUND, 'ENOENT'],
- [ERROR_PATH_NOT_FOUND, 'ENOENT'],
- [ERROR_ACCESS_DENIED, 'EACCES'],
- [ERROR_NOT_SAME_DEVICE, 'EXDEV'],
- [ERROR_FILE_EXISTS, 'EEXIST'],
- [ERROR_ALREADY_EXISTS, 'EEXIST'],
- [ERROR_INVALID_NAME, 'EINVAL'],
- [9999, 'EIO'],
- ] as const
- for (const [win32Code, code] of cases) {
- const { publishNewFileWin32 } = await importWithError(win32Code)
- await expect(publishNewFileWin32('from', 'to')).rejects.toMatchObject({ code, win32Code, path: 'from', dest: 'to' })
- }
- })
- it('creates missing directories through staging siblings and tolerates an already-created race', async () => {
- const root = await tempRoot()
- const raced = join(root, 'raced')
- const { ensureDurableDirectoryWin32 } = await importWithMove((existing, replacement, flags, setLastError) => {
- expect(flags).toBe(MOVEFILE_WRITE_THROUGH)
- const from = stripNamespace(existing)
- const to = stripNamespace(replacement)
- if (to === raced) {
- mkdirSync(to)
- setLastError(ERROR_ALREADY_EXISTS)
- return 0
- }
- if (!existsSync(from)) { setLastError(ERROR_FILE_NOT_FOUND); return 0 }
- if (existsSync(to)) { setLastError(ERROR_ALREADY_EXISTS); return 0 }
- renameSync(from, to)
- return 1
- })
- await ensureDurableDirectoryWin32(join(root, 'a', 'b'))
- expect(existsSync(join(root, 'a', 'b'))).toBe(true)
- await ensureDurableDirectoryWin32(join(root, 'a', 'b'))
- await ensureDurableDirectoryWin32(raced)
- expect(existsSync(raced)).toBe(true)
- })
- it('surfaces directory publication failures other than an existing-target race', async () => {
- const { ensureDurableDirectoryWin32 } = await importWithError(ERROR_ACCESS_DENIED)
- const root = await tempRoot()
- await expect(ensureDurableDirectoryWin32(join(root, 'denied'))).rejects.toMatchObject({ code: 'EACCES' })
- })
- it('rejects a non-directory component instead of treating it as missing', async () => {
- const { ensureDurableDirectoryWin32 } = await importWithFilesystemMove()
- const root = await tempRoot()
- const blocked = join(root, 'blocked')
- writeFileSync(blocked, 'x')
- await expect(ensureDurableDirectoryWin32(join(blocked, 'child'))).rejects.toMatchObject({ code: 'ENOTDIR' })
- })
- })
|