Files
orca/config/scripts/native-build/composition/build-native-for-platform.test.mjs
OrcaWinandOrcaWin 0b5a3a4ad9 test: remove 209 low-value tests and 20 entire suites (#38605)
* test: remove low-value mobile browser tests

* test: remove low-value mobile browser tests

* test: remove native build capability replays and pin inventories

---------

Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-11-05 10:08:14 -08:00

212 lines
8.2 KiB
JavaScript

import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { afterEach, describe, expect, it } from 'vitest'
import { spawnProcess } from '@orca/process-host'
const buildScript = fileURLToPath(new URL('./build-native-for-platform.mjs', import.meta.url))
const BUILD_COUNT = 4
const directories = []
const children = []
const buildPids = new Set()
afterEach(() => {
for (const child of children.splice(0)) {
child.kill('SIGKILL')
}
for (const pid of buildPids) {
try {
process.kill(-pid, 'SIGKILL')
} catch {}
}
buildPids.clear()
for (const directory of directories.splice(0)) {
rmSync(directory, { recursive: true, force: true })
}
})
function startBuild(mode, options = {}) {
const directory = mkdtempSync(join(tmpdir(), 'orca-native-build-test-'))
directories.push(directory)
const cli = join(directory, 'fake-pnpm.mjs')
const journal = join(directory, 'events.jsonl')
writeFileSync(journal, '')
writeFileSync(
cli,
`
import { appendFileSync, existsSync } from 'node:fs'
import { spawn } from 'node:child_process'
const name = process.argv.at(-1)
const delay = name.includes('computer') ? 0 : name.includes('keyboard') ? 200 : 400
const record = (event, extra = {}) => appendFileSync(process.env.NATIVE_BUILD_JOURNAL, JSON.stringify({ name, event, pid: process.pid, ...extra }) + '\\n')
const finish = (signal) => { record(signal); process.exit(process.env.NATIVE_BUILD_MODE === 'failure-status' ? 9 : 0) }
if (process.env.NATIVE_BUILD_MODE !== 'signal-default') process.on('SIGTERM', () => { if (process.env.NATIVE_BUILD_MODE !== 'ignore') setTimeout(() => finish('SIGTERM'), delay) })
if (process.env.NATIVE_BUILD_MODE !== 'signal-default' || !name.includes('computer')) process.on('SIGINT', () => setTimeout(() => finish('SIGINT'), delay))
process.on('SIGHUP', () => setTimeout(() => finish('SIGHUP'), delay))
record('started')
process.stdout.write('ready ' + process.pid + '\\n')
if (process.env.NATIVE_BUILD_MODE.startsWith('descendant')) {
spawn(process.execPath, ['-e', ${JSON.stringify("process.on('SIGTERM', () => {}); console.log('descendant ' + process.pid); setInterval(() => {}, 1000)")}], { stdio: 'inherit' })
}
setInterval(() => {
if (!existsSync(process.env.NATIVE_BUILD_GATE)) return
if (process.env.NATIVE_BUILD_MODE.startsWith('output-closed-')) {
const target = process.env.NATIVE_BUILD_MODE.endsWith('stderr') ? process.stderr : process.stdout
if (name.includes('computer')) target.write('compiler progress\\n')
return
}
if (['success', 'descendant-success'].includes(process.env.NATIVE_BUILD_MODE)) { record('completed'); process.exit(0) }
if (!name.includes('computer')) return
record('failed')
if (process.env.NATIVE_BUILD_MODE === 'failure-signal') process.kill(process.pid, 'SIGALRM')
else if (process.env.NATIVE_BUILD_MODE === 'failure-sigpipe') { process.on('SIGPIPE', () => {}); process.removeAllListeners('SIGPIPE'); process.kill(process.pid, 'SIGPIPE') }
else process.exit(7)
}, 10)
`
)
const child = spawnProcess({
program: process.execPath,
args: [buildScript],
cwd: directory,
env: {
...process.env,
ORCA_BACKGROUND_LAUNCH: '1',
npm_execpath: options.missingCli ? join(directory, 'missing-pnpm') : cli,
NATIVE_BUILD_JOURNAL: journal,
NATIVE_BUILD_GATE: join(directory, 'release'),
NATIVE_BUILD_MODE: mode
},
stdio: ['ignore', 'pipe', 'pipe']
})
children.push(child)
let output = ''
let stderr = ''
let descendantPids = []
let readyResolve
const ready = new Promise((resolve) => {
readyResolve = resolve
})
child.stdout.on('data', (chunk) => {
output += chunk.toString()
const pids = [...output.matchAll(/ready (\d+)/g)].map((match) => Number(match[1]))
descendantPids = [...output.matchAll(/descendant (\d+)/g)].map((match) => Number(match[1]))
for (const pid of pids) {
buildPids.add(pid)
}
if (
pids.length === BUILD_COUNT &&
(!mode.startsWith('descendant') || descendantPids.length === BUILD_COUNT)
) {
readyResolve()
}
})
child.stderr.on('data', (chunk) => {
stderr += chunk.toString()
})
const closed = new Promise((resolve, reject) => {
child.on('error', reject)
child.on('close', (code, signal) => resolve({ code, signal, output, stderr }))
})
return {
child,
ready,
closed,
descendants: () => descendantPids,
release: () => writeFileSync(join(directory, 'release'), ''),
events: () =>
readFileSync(journal, 'utf8')
.trim()
.split('\n')
.filter(Boolean)
.map((line) => JSON.parse(line))
}
}
describe.skipIf(process.platform !== 'darwin')('parallel native builds', () => {
it('reports the first failure, not the status of siblings it cancelled', async () => {
const build = startBuild('failure-status')
await build.ready
build.release()
expect(await build.closed).toMatchObject({ code: 7, signal: null })
expect(build.events().filter(({ event }) => event === 'SIGTERM')).toHaveLength(BUILD_COUNT - 1)
})
it('re-raises the signal that killed a build', async () => {
const build = startBuild('failure-signal')
await build.ready
build.release()
expect(await build.closed).toMatchObject({ code: null, signal: 'SIGALRM' })
expect(build.events().filter(({ event }) => event === 'SIGTERM')).toHaveLength(BUILD_COUNT - 1)
})
it('fails when the signal that killed a build is one the launcher ignores', async () => {
const build = startBuild('failure-sigpipe')
await build.ready
build.release()
expect(await build.closed).toMatchObject({ code: 1, signal: null })
expect(build.events().filter(({ event }) => event === 'SIGTERM')).toHaveLength(BUILD_COUNT - 1)
})
it('lets siblings finish SIGINT cleanup when one child uses the default handler', async () => {
const build = startBuild('signal-default')
await build.ready
build.child.kill('SIGINT')
expect(await build.closed).toMatchObject({ code: null, signal: 'SIGINT' })
expect(build.events().filter(({ event }) => event === 'SIGINT')).toHaveLength(BUILD_COUNT - 1)
})
it('forces a sibling that ignores graceful cancellation to exit', async () => {
const build = startBuild('ignore')
await build.ready
build.release()
expect(await build.closed).toMatchObject({ code: 7, signal: null })
for (const { pid } of build.events().filter(({ event }) => event === 'started')) {
expect(() => process.kill(pid, 0)).toThrow()
}
})
it.each(['stdout', 'stderr'])(
'stops quiet siblings when the %s consumer closes',
async (target) => {
const build = startBuild(`output-closed-${target}`)
await build.ready
build.child[target].destroy()
build.release()
const result = await build.closed
expect(result).toMatchObject({ code: 1, signal: null })
expect(result.stderr).not.toContain('Unhandled')
for (const { pid } of build.events().filter(({ event }) => event === 'started')) {
expect(() => process.kill(pid, 0)).toThrow()
}
}
)
it('reports a missing build command without waiting forever', async () => {
const build = startBuild('success', { missingCli: true })
expect(await build.closed).toMatchObject({ code: 1, signal: null })
})
it('reaps compiler descendants that retain pipes after their launcher exits', async () => {
const build = startBuild('descendant')
await build.ready
build.child.kill('SIGTERM')
expect(await build.closed).toMatchObject({ code: null, signal: 'SIGTERM' })
for (const pid of build.descendants()) {
expect(() => process.kill(pid, 0)).toThrow()
}
})
it("reaps descendants that keep a finished build's pipes open instead of hanging", async () => {
const build = startBuild('descendant-success')
await build.ready
build.release()
expect(await build.closed).toMatchObject({ code: 0, signal: null })
expect(build.events().filter(({ event }) => event === 'completed')).toHaveLength(BUILD_COUNT)
for (const pid of build.descendants()) {
expect(() => process.kill(pid, 0)).toThrow()
}
})
})