computerImages.test.ts 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940
  1. // @vitest-environment node
  2. import {it,expect,vi} from 'vitest'
  3. import {mkdtemp,rm,writeFile,readFile} from 'node:fs/promises'
  4. import {tmpdir} from 'node:os'
  5. import {join} from 'node:path'
  6. import {ComputerImages,fileSHA256,imageManifest,writeManifest} from '../../src/runner/computers/images'
  7. const id='sha256:'+'a'.repeat(64)
  8. const detail={Id:id,Os:'linux',Architecture:'arm64',Config:{Labels:{'com.openmausbot.cua-driver':'0.20.0','com.openmausbot.image-layer':'5'}}}
  9. it('checks immutable identity, architecture and driver before accepting an image',async()=>{
  10. const run=vi.fn().mockResolvedValue(JSON.stringify([detail])),images=new ComputerImages('docker',run)
  11. expect(await images.inspect(id)).toMatchObject({protocol:1,imageId:id,architecture:'arm64'})
  12. await expect(images.inspect('mutable:latest')).rejects.toThrow()
  13. run.mockResolvedValue(JSON.stringify([{...detail,Id:'sha256:'+'b'.repeat(64)}]))
  14. await expect(images.inspect(id)).rejects.toThrow('身份')
  15. run.mockResolvedValue(JSON.stringify([{...detail,Architecture:'unknown'}]))
  16. await expect(images.inspect(id)).rejects.toThrow()
  17. })
  18. it('rejects damaged offline archives before invoking the engine',async()=>{
  19. const home=await mkdtemp(join(tmpdir(),'yaoyao-image-')),path=join(home,'image.tar'),run=vi.fn()
  20. try{
  21. await writeFile(path,'fixture image')
  22. const manifest=imageManifest.parse({protocol:1,imageId:id,architecture:'arm64',driver:'0.20.0',layer:'5',createdAt:1,archiveSha256:await fileSHA256(path)})
  23. await writeManifest(path+'.json',manifest);await writeFile(path,'damaged image')
  24. await expect(new ComputerImages('docker',run).import(path)).rejects.toThrow('校验失败')
  25. expect(run).not.toHaveBeenCalled()
  26. expect(JSON.parse(await readFile(path+'.json','utf8'))).toEqual(manifest)
  27. }finally{await rm(home,{recursive:true,force:true})}
  28. })
  29. it('never overwrites an existing archive and health-checks imported identity',async()=>{
  30. const home=await mkdtemp(join(tmpdir(),'yaoyao-image-')),path=join(home,'image.tar')
  31. const run=vi.fn().mockResolvedValue(JSON.stringify([detail])),images=new ComputerImages('podman',run),verify=vi.spyOn(images,'verify').mockResolvedValue()
  32. try{
  33. await writeFile(path,'original')
  34. await expect(images.export(id,path)).rejects.toMatchObject({code:'EEXIST'})
  35. expect(await readFile(path,'utf8')).toBe('original')
  36. await writeManifest(path+'.json',{protocol:1,imageId:id,architecture:'arm64',driver:'0.20.0',layer:'5',createdAt:1,archiveSha256:await fileSHA256(path)})
  37. await images.import(path)
  38. expect(run).toHaveBeenCalledWith('podman',['load','--input',path]);expect(verify).toHaveBeenCalledOnce()
  39. }finally{await rm(home,{recursive:true,force:true})}
  40. })