Просмотр исходного кода

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

test(ci): repair platform fixtures, gallery clock and cache teardown
Turtle 1 месяц назад
Родитель
Сommit
6a4a825a88

+ 5 - 3
apps/web/tests/clickable-links-gallery.e2e.ts

@@ -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
packages/fs/fs-local/tests/fsio.spec.ts

@@ -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)

+ 4 - 1
packages/subagent/subagent/tests/list-children.spec.ts

@@ -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)

+ 7 - 3
packages/subprocess/subprocess-local/tests/linux-scope.spec.ts

@@ -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 })