| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 |
- // @vitest-environment node
- import {expect,it} from 'vitest'
- import {mkdtemp,rm,readFile,writeFile,mkdir} from 'node:fs/promises'
- import {tmpdir} from 'node:os'
- import {join} from 'node:path'
- import {DatabaseSync} from 'node:sqlite'
- import {ComputerPool} from '../../src/runner/computers/pool'
- import {randomUUID} from 'node:crypto'
- import {ContainerComputerProvider,CUA_DRIVER,CUA_SOCKET,type ComputerSpecification} from '../../src/runner/computers/container'
- // Only creates a UUID-owned private fixture; never adopts user containers.
- it.skipIf(!process.env.YAOYAO_COMPUTER_IMAGE)('executes in a real private computer and preserves its workspace across recreation',async()=>{
- const home=await mkdtemp(join(tmpdir(),'yaoyao-computer-live-'))
- const provider=new ContainerComputerProvider('docker',randomUUID(),home)
- const spec:ComputerSpecification={id:randomUUID(),ownerKey:randomUUID(),imageId:process.env.YAOYAO_COMPUTER_IMAGE!}
- const db=new DatabaseSync(':memory:'),pool=new ComputerPool(db,provider)
- try {
- await pool.recover()
- const lease=await pool.acquire(spec,'initial-task',()=>{})
- const initial=(await provider.inspect(spec))!
- expect(initial.running).toBe(true)
- expect((await provider.execute(spec,['ls','/sys/class/net'],{authorize:()=>{}})).stdout.trim()).toBe('lo')
- const result=await provider.execute(spec,['/bin/sh','-c','id -u; printf isolated-fixture > persistence-proof.txt; pwd'],{authorize:()=>{}})
- expect(result.stdout).toContain('1000\n');expect(result.stdout).toContain('/home/cua/workspace')
- expect(await readFile(join(initial.workspace,'persistence-proof.txt'),'utf8')).toBe('isolated-fixture')
- let healthError=''
- try{await expect.poll(async()=>{
- try{return await provider.health(spec,()=>{})}catch(error){healthError=`${String(error)} ${String((error as any).stderr??'')}`;return null}
- },{timeout:60000,interval:1000}).toMatchObject({schema_version:'1'})}catch{
- const diagnostics=await provider.run('docker',['logs','--tail','70',initial.containerId]).catch(()=>({stdout:'',stderr:''}))
- const vnc=await provider.run('docker',['exec','--user','0',initial.containerId,'/bin/sh','-c','tail -40 /var/log/supervisor/vncserver* /home/cua/.vnc/*.log 2>/dev/null']).catch(error=>({stdout:String(error.stdout??''),stderr:String(error.stderr??'')}))
- throw new Error(`Computer health: ${healthError}\n${diagnostics.stdout}\n${diagnostics.stderr}\n${vnc.stdout}\n${vnc.stderr}`)
- }
- await provider.execute(spec,[CUA_DRIVER,'call','get_desktop_state','{}','--socket',CUA_SOCKET,'--screenshot-out-file','/tmp/yaoyao-computer-proof.png'],{authorize:()=>{}})
- const screenshot=Buffer.from((await provider.execute(spec,['base64','-w0','/tmp/yaoyao-computer-proof.png'],{authorize:()=>{}})).stdout.trim(),'base64')
- expect(screenshot.subarray(1,4).toString()).toBe('PNG');expect(screenshot.byteLength).toBeGreaterThan(1024)
- await mkdir('test-results/computer',{recursive:true});await writeFile('test-results/computer/desktop.png',screenshot)
- await pool.release(lease)
- const nextLease=await pool.acquire(spec,'next-task',()=>{})
- const recreated=(await provider.inspect(spec))!
- expect(recreated.containerId).not.toBe(initial.containerId)
- expect((await provider.execute(spec,['cat','persistence-proof.txt'],{authorize:()=>{}})).stdout).toBe('isolated-fixture')
- const pending=pool.use(nextLease,context=>provider.execute(spec,['/bin/sh','-c','sleep 30; printf should-not-run > cancelled-proof.txt'],context))
- const settled=pending.catch(error=>error)
- await new Promise(resolve=>setTimeout(resolve,500));await pool.release(nextLease)
- expect(await settled).toBeInstanceOf(Error)
- expect(await provider.inspect(spec)).toBeUndefined()
- expect(()=>pool.use(lease,async()=>{})).toThrow('电脑控制权已改变')
- await expect(readFile(join(initial.workspace,'cancelled-proof.txt'))).rejects.toMatchObject({code:'ENOENT'})
- }finally{await pool.close();await provider.remove(spec);db.close();await rm(home,{recursive:true,force:true})}
- },100000)
|