Merge pull request #4079 from deepseek-harness/turtle/master-ci-platform-tests

test(ci): repair platform fixtures, gallery clock and cache teardown
This commit is contained in:
Turtle authored and GitHub committed 2026-09-14 12:39:59 +08:00
commit 6a4a825a88
4 files changed
+18 -8

No files matched your search

@@ -45,6 +45,8 @@ const OVERLAY = fileURLToPath(new URL('./produced-files.overlay.yml', import.met
const MODE = webSnapshotMode()
const SEED_ID = 'clickable-links-gallery-web-e2e'
const DONE = 'LINK_GALLERY_DONE'
// Seeded events and browser time share a day independently of host timezones.
const GALLERY_TIME = Date.UTC(2026, 0, 15, 12)
const GUIDE_URL = 'https://docs.example.test/guide'
const API_URL = 'https://docs.example.test/api'
@@ -192,7 +194,6 @@ const CALLS: GalleryCall[] = [
*/
function galleryFixture(imageUrl: string): string {
const session = Session.create(SessionId('clickable-links-gallery-source'))
const eventTimeOrigin = new Date().setHours(12, 0, 0, 0)
session.append('turn/start', { turn: 1 })
const user = session.append('user/message', createUserMessage({
content: text('Assemble the link gallery: write the report and styles, inspect the sources, and summarize.'),
@@ -289,7 +290,7 @@ function galleryFixture(imageUrl: string): string {
}),
...session.snapshotEvents().map(event => JSON.stringify({
...event,
time: eventTimeOrigin + event.seq * 1_000,
time: GALLERY_TIME + event.seq * 1_000,
})),
'',
].join('\n')
@@ -305,9 +306,10 @@ describe('web e2e: clickable links gallery', () => {
beforeAll(async () => {
scaffold = await launchWebScaffold({ extraOverlayPath: OVERLAY })
imageUrl = new URL('/favicon.svg', scaffold.baseUrl).toString()
await seedSession(scaffold, galleryFixture(imageUrl), SEED_ID)
await seedSession(scaffold, galleryFixture(imageUrl), SEED_ID, undefined, { createdAt: GALLERY_TIME })
browser = await chromium.launch()
page = await newEnglishPage(browser)
await page.clock.setFixedTime(GALLERY_TIME + 60_000)
tripwire = watchConsole(page)
await page.goto(scaffold.authenticatedUrl, { waitUntil: 'load' })
await page.waitForSelector('[class*="frame"]', { timeout: 30_000 })
+2 -1
View File
@@ -110,7 +110,8 @@ describe('resolveLocalTarget', () => {
await mkdir(join(dir, 'nested'))
await writeFile(join(dir, 'created.txt'), 'native')
const drive = parse(dir).root.slice(0, 2)
const driveCwd = `${drive}${relative(process.cwd(), dir)}`
// Resolve the temp drive independently when the checkout lives on another volume.
const driveCwd = `${drive}${relative(resolve(drive), dir)}`
for (const cwd of [dir, driveCwd]) {
for (const requested of ['created.txt', `${drive}nested/../created.txt`]) {
const target = await resolveLocalTarget(cwd, requested)
@@ -35,10 +35,12 @@ import { seedStoredSession } from './persistence-helpers.ts'
type Script = ConstructorParameters<typeof MockAdapter>[0]
const roots: string[] = []
const projectionCacheDisposers: Array<() => Promise<void>> = []
const persistenceDisposers: Array<() => Promise<void>> = []
const projCacheRoots: string[] = []
afterEach(async () => {
await Promise.all(projectionCacheDisposers.splice(0).map(dispose => dispose()))
await Promise.all(persistenceDisposers.splice(0).map(dispose => dispose()))
for (const root of projCacheRoots.splice(0)) rmSync(root, { recursive: true, force: true })
for (const root of roots.splice(0)) rmSync(root, { recursive: true, force: true, maxRetries: 10, retryDelay: 100 })
@@ -64,7 +66,8 @@ async function setup(
await ctx.plugin(Storage)
await ctx.plugin({ name: storageJsonName, inject: storageJsonInject, apply: storageJsonApply, Config: storageJsonConfig }, { root })
await ctx.plugin({ name: storageDomainName, inject: storageDomainInject, apply: storageDomainApply, Config: storageDomainConfig }, { backend: 'json' })
await ctx.plugin(SessionProjectionCache, { writeEveryEvents: 100, writeIntervalMs: 60_000 })
const cache = await ctx.plugin(SessionProjectionCache, { writeEveryEvents: 100, writeIntervalMs: 60_000 })
projectionCacheDisposers.push(() => cache.dispose())
}
await ctx.plugin(TestSessionQuery)
await ctx.plugin(SubagentRuntime)
@@ -288,10 +288,14 @@ describe('Linux scope establishment and quiescence', () => {
result.owner.cleanup?.()
})
it('accepts request consumption followed by rapid --collect unload as stopped', async () => {
it.each([undefined, 'pipe'] as const)('accepts request consumption and rapid --collect unload with control %s', async (control) => {
const states = [activeUnit(), unloadedUnit()]
const { child, result, requestPath } = launch(async () => states.shift() ?? missingUnit())
expect(consumeLinuxLaunchRequest(requestPath)).toEqual({ cwd: '/target', env: { TARGET: 'yes' } })
const controlOptions = control === undefined ? {} : { control }
const { child, result, requestPath } = launch(async () => states.shift() ?? missingUnit(), {}, {
...spec(), stdio: { ...spec().stdio, ...controlOptions },
})
expect(consumeLinuxLaunchRequest(requestPath)).toEqual({ cwd: '/target', env: { TARGET: 'yes' }, ...controlOptions })
expect(result.control).toBe(control === undefined ? undefined : child.control)
const waiting = result.owner.waitForExit()
child.exit(0, null)
await expect(result.direct).resolves.toEqual({ exitCode: 0, signal: null })