Run Node event-loop measurement after ordinary test suites (#26015)

This commit is contained in:
Neil
2026-10-06 18:08:50 -07:00
committed by GitHub
parent c0273b1ff7
commit 3fb72d135d
3 changed files with 116 additions and 24 deletions
+55 -1
View File
@@ -7,6 +7,9 @@ import { balanceFiles } from './ci-shard-assignment.mjs'
import { discoverE2eFiles, planE2e } from './ci-e2e-shard-plan.mjs'
import { parseTimingLog } from './ci-shard-timing-import.mjs'
import TimingSequencer from './ci-unit-sequencer.mjs'
import { UNIT_INCLUDE, UNIT_EXCLUDE } from './ci-unit-files.mjs'
import { NODE_RUNTIME_INCLUDE } from './vitest-node-runtime-files.mjs'
import { nodeRuntimePool } from './vitest-node-runtime-pool'
const directories = []
afterEach(() => {
@@ -60,10 +63,61 @@ describe('timing-weighted shard selection', () => {
expect(new Set(selected)).toEqual(new Set(specs))
})
it('wires a constructor into the opt-in Vitest config', async () => {
it('keeps global sharding and runs the Node measurement after ordinary projects', async () => {
vi.stubEnv('ORCA_BALANCE_UNIT_SHARDS', '1')
const { default: config } = await import('../vitest.config')
expect(config.test.sequence.sequencer).toBe(TimingSequencer)
expect(config.test.maxWorkers).toBe(process.platform === 'win32' ? 4 : undefined)
const measurementFile =
'src/main/foreign-sqlite-readers/foreign-sqlite-reader-event-loop.test.ts'
const projects = config.test.projects
const measurement = projects.filter((project) => project.test.name === 'node-measurement')
const ordinary = projects.filter((project) => project.test.name !== 'node-measurement')
expect(measurement).toHaveLength(1)
expect(ordinary).toHaveLength(process.versions.bun ? 2 : 1)
expect(measurement[0].test).toMatchObject({
include: [measurementFile],
exclude: UNIT_EXCLUDE,
maxWorkers: 1,
sequence: { groupOrder: 2 },
env: { ORCA_VITEST_RUNTIME: process.versions.bun ? 'node-runtime' : 'node' },
pool: process.versions.bun ? 'node-runtime' : 'forks'
})
expect(measurement[0].test.poolRunner).toBe(process.versions.bun ? nodeRuntimePool : undefined)
for (const project of ordinary) {
expect(project.test.sequence.groupOrder).toBe(1)
expect(project.test.exclude).toContain(measurementFile)
}
const ordinaryNode = ordinary.find((project) => project.test.name !== 'bun')
expect(ordinaryNode.test.include).toEqual(
process.versions.bun ? NODE_RUNTIME_INCLUDE : UNIT_INCLUDE
)
const ordinaryBun = ordinary.find((project) => project.test.name === 'bun')
if (process.versions.bun) {
expect(ordinaryBun.test.exclude).toEqual(
expect.arrayContaining([...NODE_RUNTIME_INCLUDE, measurementFile])
)
}
for (const project of projects) {
expect(project.extends).toBe(false)
expect(project.define).toEqual(config.define)
expect(project.resolve).toEqual(config.resolve)
expect(project.test.execArgv).toEqual(['--no-experimental-webstorage', '--expose-gc'])
expect(project.test.setupFiles).toEqual([
resolve('config/scripts/vitest-real-agent-home-write-guard.ts'),
resolve('config/scripts/vitest-bun-node-builtins.ts'),
resolve('config/scripts/happy-dom-offscreen-canvas.ts'),
resolve('config/scripts/happy-dom-mutation-observer-retention.ts'),
resolve('config/scripts/vitest-host-ports-setup.ts'),
resolve('config/scripts/vitest-caller-identity-env-setup.ts')
])
expect(project.test).toMatchObject({
environment: 'node',
server: { deps: { inline: ['zod'] } },
hookTimeout: 60_000,
testTimeout: 30_000
})
}
})
it('keeps nested/serial E2E files atomic and fails closed on discovery errors', () => {
+19 -3
View File
@@ -1,4 +1,4 @@
import { mkdtempSync, writeFileSync, rmSync } from 'node:fs'
import { mkdtempSync, readFileSync, writeFileSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterEach, expect, it, vi } from 'vitest'
@@ -22,7 +22,12 @@ it.each([
'empty-selection'
])('preserves complete shard coverage with %s planning evidence', async (kind) => {
root = mkdtempSync(join(tmpdir(), 'unit-sequencer-'))
const files = ['src/a.test.ts', 'src/b.test.ts', 'src/c.test.ts', 'src/d.test.ts']
const files = [
'src/main/foreign-sqlite-readers/foreign-sqlite-reader-event-loop.test.ts',
'src/b.test.ts',
'src/c.test.ts',
'src/d.test.ts'
]
const plan = {
version: 1,
sourceSha: kind === 'stale' ? 'old' : 'current',
@@ -44,8 +49,19 @@ it.each([
const assigned = []
for (const index of [1, 2]) {
const sequencer = new TimingSequencer({ config: { root, shard: { index, count: 2 } } })
const specs = files.map((file) => ({ moduleId: join(root, file) }))
const specs = files.map((file, position) => ({
moduleId: join(root, file),
project: {
name: position === 0 ? 'node-measurement' : position % 2 ? 'bun' : 'node-runtime',
config: { sequence: { groupOrder: position === 0 ? 2 : 1 }, isolate: true }
}
}))
assigned.push(...(await sequencer.shard(specs)).map((spec) => spec.moduleId))
const manifest = JSON.parse(readFileSync(join(root, 'assignment.json'), 'utf8'))
expect(manifest.selectedShard).toBe(index)
expect(manifest.shards.flatMap((shard) => shard.files).sort()).toEqual(
(kind === 'valid' ? files.slice(0, 2) : files).toSorted()
)
}
expect(assigned.sort()).toEqual(
(kind === 'valid' ? files.slice(0, 2) : files).map((file) => join(root, file)).sort()
+42 -20
View File
@@ -7,6 +7,7 @@ import { NODE_RUNTIME_INCLUDE } from './scripts/vitest-node-runtime-files.mjs'
import { nodeRuntimePool } from './scripts/vitest-node-runtime-pool'
const balancedShards = process.env.ORCA_BALANCE_UNIT_SHARDS === '1'
const measurementFile = 'src/main/foreign-sqlite-readers/foreign-sqlite-reader-event-loop.test.ts'
const transforms = {
define: { ORCA_FEATURE_WALL_ENABLED: 'true' },
resolve: {
@@ -39,28 +40,49 @@ const testOptions = {
hookTimeout: 60_000,
testTimeout: 30_000
}
const nodeProject = {
extends: false,
...transforms,
test: {
...testOptions,
name: process.versions.bun ? 'node-runtime' : 'node',
env: { ORCA_VITEST_RUNTIME: process.versions.bun ? 'node-runtime' : 'node' },
include: process.versions.bun ? NODE_RUNTIME_INCLUDE : UNIT_INCLUDE,
exclude: [...testOptions.exclude, measurementFile],
sequence: { groupOrder: 1 },
...(process.versions.bun
? { pool: 'node-runtime', poolRunner: nodeRuntimePool }
: { pool: 'forks' })
}
}
const projects = [
...(process.versions.bun
? [
{
extends: false,
...transforms,
test: {
...testOptions,
name: 'bun',
env: { ORCA_VITEST_RUNTIME: 'bun' },
pool: 'forks',
exclude: [...testOptions.exclude, ...NODE_RUNTIME_INCLUDE, measurementFile],
sequence: { groupOrder: 1 }
}
}
]
: []),
nodeProject,
// Keep the event-loop measurement free of other suites without weakening its limits.
{
extends: false,
...transforms,
...nodeProject,
test: {
...testOptions,
name: 'bun',
env: { ORCA_VITEST_RUNTIME: 'bun' },
pool: 'forks',
exclude: [...testOptions.exclude, ...NODE_RUNTIME_INCLUDE]
}
},
{
extends: false,
...transforms,
test: {
...testOptions,
name: 'node-runtime',
env: { ORCA_VITEST_RUNTIME: 'node-runtime' },
include: NODE_RUNTIME_INCLUDE,
pool: 'node-runtime',
poolRunner: nodeRuntimePool
...nodeProject.test,
name: 'node-measurement',
include: [measurementFile],
exclude: testOptions.exclude,
maxWorkers: 1,
sequence: { groupOrder: 2 }
}
}
]
@@ -75,7 +97,7 @@ export default defineConfig({
reporters: ['default', resolve('config/scripts/ci-unit-timing-reporter.mjs')]
}
: {}),
...(process.versions.bun ? { projects } : {}),
projects,
...(process.platform === 'win32' ? { maxWorkers: 4 } : {})
}
})