tar.spec.ts 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. /**
  2. * The bare-tar image codec: byte-faithful roundtrip through packTar/parseTar
  3. * and the VFS mount the worker performs on that archive.
  4. */
  5. import { describe, expect, it } from 'vitest'
  6. import { packTar, parseTar } from '../../src/storage/tar.ts'
  7. import { loadVfsImage, loadVfsOverlay } from '../../src/storage/memory.ts'
  8. const encoder = new TextEncoder()
  9. describe('tar codec', () => {
  10. it('roundtrips files and empty directories byte-faithfully', () => {
  11. const payload = new Uint8Array([0, 1, 2, 253, 254, 255])
  12. const files = {
  13. 'config/cordis.yml': encoder.encode('- id: subject\n'),
  14. 'node_modules/pkg/lib/index.js': payload,
  15. 'home/': new Uint8Array(0),
  16. }
  17. const entries = parseTar(packTar(files))
  18. const byName = new Map(entries.map(entry => [entry.name, entry]))
  19. expect([...byName.keys()].sort()).toEqual(Object.keys(files).sort())
  20. expect([...byName.get('node_modules/pkg/lib/index.js')!.bytes]).toEqual([...payload])
  21. expect(byName.get('home/')!.bytes.byteLength).toBe(0)
  22. // The header mode field carries the packed permission bits: normal
  23. // 644/755, which the VFS mount reports back through stat.
  24. expect(byName.get('node_modules/pkg/lib/index.js')!.mode).toBe(0o644)
  25. expect(byName.get('home/')!.mode).toBe(0o755)
  26. })
  27. it('mounts as a VFS with directories synthesized along file paths', () => {
  28. const vfs = loadVfsImage(packTar({
  29. 'config/cordis.yml': encoder.encode('- id: subject\n'),
  30. 'workspace/': new Uint8Array(0),
  31. }), '/dsh')
  32. expect(vfs.existsSync('/dsh/config/cordis.yml')).toBe(true)
  33. expect(vfs.readFileSync('/dsh/config/cordis.yml', 'utf8')).toBe('- id: subject\n')
  34. expect(vfs.existsSync('/dsh/config')).toBe(true)
  35. expect(vfs.existsSync('/dsh/workspace')).toBe(true)
  36. expect(vfs.existsSync('/dsh/absent')).toBe(false)
  37. })
  38. it('applies ordered data overlays without exposing runtime paths', () => {
  39. const vfs = loadVfsImage(packTar({
  40. 'config/cordis.yml': encoder.encode('- id: subject\n'),
  41. 'workspace/status.txt': encoder.encode('base'),
  42. }), '/dsh')
  43. loadVfsOverlay(packTar({
  44. 'workspace/status.txt': encoder.encode('fixture'),
  45. 'home/sessions/example/session.jsonl': encoder.encode('{}\n'),
  46. }), '/dsh', vfs)
  47. expect(vfs.readFileSync('/dsh/workspace/status.txt', 'utf8')).toBe('fixture')
  48. expect(vfs.readFileSync('/dsh/home/sessions/example/session.jsonl', 'utf8')).toBe('{}\n')
  49. expect(() => loadVfsOverlay(packTar({
  50. 'config/cordis.yml': encoder.encode('replaced'),
  51. }), '/dsh', vfs)).toThrow(/overlay entry must stay under home\/ or workspace/)
  52. expect(vfs.readFileSync('/dsh/config/cordis.yml', 'utf8')).toBe('- id: subject\n')
  53. })
  54. })