mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
* ci: reuse prepared Windows security addon in PR packages * ci: prepare bounded Windows security reuse qualification * ci: ignore owned Windows benchmark receipts during source checks * test: inject Windows security qualification dependencies * test(mobile): register chat view mocks in test roots
246 lines
8.7 KiB
JavaScript
246 lines
8.7 KiB
JavaScript
import { createHash } from 'node:crypto'
|
|
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
|
import { tmpdir } from 'node:os'
|
|
import { dirname, isAbsolute, join } from 'node:path'
|
|
import { runInNewContext } from 'node:vm'
|
|
import { afterEach, expect, it, vi } from 'vitest'
|
|
import {
|
|
buildWindowsSecurityAddon,
|
|
reusePreparedWindowsSecurityAddon
|
|
} from './build-windows-security-addon.mjs'
|
|
import { peImage } from './windows-pe-image-fixture.mjs'
|
|
|
|
const roots = []
|
|
afterEach(() => {
|
|
vi.unstubAllGlobals()
|
|
roots.splice(0).forEach((root) => rmSync(root, { recursive: true, force: true }))
|
|
})
|
|
|
|
const success = { code: 0, timedOut: false, outputTruncated: false, stdout: '' }
|
|
function fixture(arch = 'x64') {
|
|
const root = mkdtempSync(join(tmpdir(), 'windows-security-build-'))
|
|
roots.push(root)
|
|
const candidate = join(root, 'native/windows-security/build/Release/orca_windows_security.node')
|
|
mkdirSync(dirname(candidate), { recursive: true })
|
|
writeFileSync(candidate, peImage({ arch }))
|
|
mkdirSync(join(root, 'native/windows-security/src'))
|
|
writeFileSync(join(root, 'native/windows-security/binding.gyp'), '{}')
|
|
writeFileSync(join(root, 'native/windows-security/src/addon.cc'), 'source')
|
|
const runtimePath = join(root, 'pinned node.exe')
|
|
writeFileSync(runtimePath, 'pinned Node fixture')
|
|
const executableSha256 = createHash('sha256').update('pinned Node fixture').digest('hex')
|
|
const runtimeAssets = { [`win32-${arch}`]: { executableSha256 } }
|
|
const output = join(root, 'output/windows-security.node')
|
|
const run = vi.fn((invocation) => {
|
|
if (invocation.args.includes('rebuild')) {
|
|
const built = join(invocation.cwd, 'build/Release/orca_windows_security.node')
|
|
mkdirSync(dirname(built), { recursive: true })
|
|
writeFileSync(
|
|
built,
|
|
peImage({ arch: invocation.args.find((arg) => arg.startsWith('--arch=')).slice(7) })
|
|
)
|
|
return success
|
|
}
|
|
return {
|
|
...success,
|
|
stdout: invocation.program === runtimePath ? 'windows-security-ready' : ''
|
|
}
|
|
})
|
|
return {
|
|
candidate,
|
|
output,
|
|
options: {
|
|
enabled: true,
|
|
root,
|
|
runtimePath,
|
|
platform: 'win32',
|
|
hostArch: arch,
|
|
runtimeAssets,
|
|
run
|
|
}
|
|
}
|
|
}
|
|
|
|
it.each(['x64', 'arm64'])('reuses the exact prepared %s candidate under pinned Node', (arch) => {
|
|
const { candidate, output, options } = fixture(arch)
|
|
expect(reusePreparedWindowsSecurityAddon(arch, output, options)).toBe(true)
|
|
expect(readFileSync(output)).toEqual(readFileSync(candidate))
|
|
const [preparation, probe] = options.run.mock.calls.map(([invocation]) => invocation)
|
|
expect(preparation).toEqual({
|
|
program: process.execPath,
|
|
args: [
|
|
join(options.root, 'config/scripts/ensure-native-runtime.mjs'),
|
|
'--runtime=node',
|
|
'--check-only'
|
|
],
|
|
cwd: options.root,
|
|
timeoutMs: 30_000
|
|
})
|
|
expect(probe.program).toBe(options.runtimePath)
|
|
expect(isAbsolute(probe.program)).toBe(true)
|
|
expect(probe.timeoutMs).toBe(30_000)
|
|
const requireAddon = vi.fn(() => ({ currentUserSid: () => 'S-1-5-21-123-456-789-1001' }))
|
|
const write = vi.fn()
|
|
runInNewContext(probe.args[1], {
|
|
process: { platform: 'win32', arch, versions: {}, stdout: { write } },
|
|
require: requireAddon
|
|
})
|
|
expect(requireAddon).toHaveBeenCalledWith(candidate)
|
|
expect(isAbsolute(candidate)).toBe(true)
|
|
expect(write).toHaveBeenCalledWith('windows-security-ready')
|
|
})
|
|
|
|
it.each([
|
|
{ enabled: false },
|
|
{ enabled: undefined },
|
|
{ platform: 'darwin' },
|
|
{ platform: 'linux' },
|
|
{ hostArch: 'arm64' },
|
|
{ runtimePath: undefined },
|
|
{ runtimePath: 'node.exe' }
|
|
])('declines reuse without same-host opt-in and pinned runtime: %j', (overrides) => {
|
|
const { output, options } = fixture()
|
|
expect(reusePreparedWindowsSecurityAddon('x64', output, { ...options, ...overrides })).toBe(false)
|
|
expect(options.run).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('declines missing, corrupt, wrong-architecture candidates and an unverified runtime', () => {
|
|
const { candidate, output, options } = fixture()
|
|
expect(
|
|
reusePreparedWindowsSecurityAddon('x64', output, {
|
|
...options,
|
|
runtimeAssets: undefined
|
|
})
|
|
).toBe(false)
|
|
expect(options.run).not.toHaveBeenCalled()
|
|
for (const bytes of [Buffer.from('corrupt'), peImage({ arch: 'arm64' })]) {
|
|
writeFileSync(candidate, bytes)
|
|
expect(reusePreparedWindowsSecurityAddon('x64', output, options)).toBe(false)
|
|
}
|
|
rmSync(candidate)
|
|
expect(reusePreparedWindowsSecurityAddon('x64', output, options)).toBe(false)
|
|
writeFileSync(candidate, peImage())
|
|
writeFileSync(options.runtimePath, 'different Node')
|
|
expect(reusePreparedWindowsSecurityAddon('x64', output, options)).toBe(false)
|
|
expect(options.run).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it.each([
|
|
{ code: 1 },
|
|
{ code: null },
|
|
{ timedOut: true },
|
|
{ outputTruncated: true },
|
|
{ stdout: '' },
|
|
{ stdout: 'S-1-5-21-123' },
|
|
{ stdout: 'windows-security-ready\nextra output' }
|
|
])('declines failed loading or invalid probe results: %j', (result) => {
|
|
const { output, options } = fixture()
|
|
options.run
|
|
.mockReturnValueOnce(success)
|
|
.mockReturnValueOnce({ ...success, stdout: 'windows-security-ready', ...result })
|
|
expect(reusePreparedWindowsSecurityAddon('x64', output, options)).toBe(false)
|
|
})
|
|
|
|
it.each([{ code: 1 }, { timedOut: true }, { outputTruncated: true }])(
|
|
'does not load the candidate after failed Node preparation: %j',
|
|
(result) => {
|
|
const { output, options } = fixture()
|
|
options.run.mockReturnValueOnce({ ...success, ...result })
|
|
expect(reusePreparedWindowsSecurityAddon('x64', output, options)).toBe(false)
|
|
expect(options.run).toHaveBeenCalledOnce()
|
|
}
|
|
)
|
|
|
|
it('declines probe spawn exceptions', () => {
|
|
const { output, options } = fixture()
|
|
options.run.mockImplementation(() => {
|
|
throw new Error('spawn failed')
|
|
})
|
|
expect(reusePreparedWindowsSecurityAddon('x64', output, options)).toBe(false)
|
|
})
|
|
|
|
it.each(['', undefined, 123, 'invalid', 'S-1-no-sid'])(
|
|
'the probe rejects invalid currentUserSid results: %j',
|
|
(sid) => {
|
|
const { output, options } = fixture()
|
|
reusePreparedWindowsSecurityAddon('x64', output, options)
|
|
const probe = options.run.mock.calls[1][0]
|
|
const write = vi.fn()
|
|
expect(() =>
|
|
runInNewContext(probe.args[1], {
|
|
process: {
|
|
platform: 'win32',
|
|
arch: 'x64',
|
|
versions: {},
|
|
stdout: { write },
|
|
exit: (code) => {
|
|
throw new Error(`exit ${code}`)
|
|
}
|
|
},
|
|
require: () => ({ currentUserSid: () => sid })
|
|
})
|
|
).toThrow('exit 2')
|
|
expect(write).not.toHaveBeenCalled()
|
|
}
|
|
)
|
|
|
|
it.each([
|
|
'non-opt-in',
|
|
'cold',
|
|
'corrupt',
|
|
'wrong architecture',
|
|
'cross compilation',
|
|
'load failure',
|
|
'valid'
|
|
])('the builder retains real compilation unless reuse succeeds: %s', (scenario) => {
|
|
const { candidate, output, options } = fixture()
|
|
vi.stubGlobal('process', { ...process, platform: 'win32', arch: 'x64' })
|
|
if (scenario === 'non-opt-in') {
|
|
options.enabled = false
|
|
}
|
|
if (scenario === 'cold') {
|
|
rmSync(candidate)
|
|
}
|
|
if (scenario === 'corrupt') {
|
|
writeFileSync(candidate, 'bad')
|
|
}
|
|
if (scenario === 'wrong architecture') {
|
|
writeFileSync(candidate, peImage({ arch: 'arm64' }))
|
|
}
|
|
if (scenario === 'load failure') {
|
|
options.run.mockReturnValueOnce(success).mockReturnValueOnce({ ...success, code: 1 })
|
|
}
|
|
const arch = scenario === 'cross compilation' ? 'arm64' : 'x64'
|
|
expect(buildWindowsSecurityAddon(arch, output, options)).toBe(output)
|
|
expect(
|
|
options.run.mock.calls.filter(([invocation]) => invocation.args.includes('rebuild'))
|
|
).toHaveLength(scenario === 'valid' ? 0 : 1)
|
|
})
|
|
|
|
it('standalone compilation rejects unsupported architectures and non-Windows hosts', () => {
|
|
const { output, options } = fixture()
|
|
vi.stubGlobal('process', { ...process, platform: 'linux' })
|
|
expect(() => buildWindowsSecurityAddon('ia32', output, options)).toThrow('--arch must be')
|
|
expect(() => buildWindowsSecurityAddon('x64', output, options)).toThrow('only builds on Windows')
|
|
expect(options.run).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it.each(['failed compiler', 'missing output', 'wrong machine'])(
|
|
'the cold path fails closed on %s',
|
|
(failure) => {
|
|
const { output, options } = fixture()
|
|
vi.stubGlobal('process', { ...process, platform: 'win32', arch: 'x64' })
|
|
options.enabled = false
|
|
options.run.mockImplementation((invocation) => {
|
|
if (failure === 'wrong machine') {
|
|
const built = join(invocation.cwd, 'build/Release/orca_windows_security.node')
|
|
mkdirSync(dirname(built), { recursive: true })
|
|
writeFileSync(built, peImage({ arch: 'arm64' }))
|
|
}
|
|
return { ...success, code: failure === 'failed compiler' ? 1 : 0 }
|
|
})
|
|
expect(() => buildWindowsSecurityAddon('x64', output, options)).toThrow()
|
|
expect(() => readFileSync(output)).toThrow()
|
|
}
|
|
)
|