stray-fragments.spec.ts 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. import { Context } from '@deepseek-ai/cordis'
  2. import { expect, it, vi } from 'vitest'
  3. // Keep the interpreter and pipe lifecycle real; only OS-dependent read sizes
  4. // change. Each byte reaches the runtime as its own data event.
  5. vi.mock('node:child_process', async (importOriginal) => {
  6. const actual = await importOriginal<typeof import('node:child_process')>()
  7. return {
  8. ...actual,
  9. spawn: vi.fn(actual.spawn).mockImplementation((...args) => {
  10. const child = actual.spawn(...args)
  11. const stdout = child.stdout!
  12. const emit = stdout.emit.bind(stdout)
  13. stdout.emit = (event: string | symbol, ...values: unknown[]) => {
  14. if (event !== 'data') return emit(event, ...values)
  15. const chunk = values[0] as Buffer
  16. for (let offset = 0; offset < chunk.length; offset++) {
  17. emit('data', chunk.subarray(offset, offset + 1))
  18. }
  19. return true
  20. }
  21. return child
  22. }),
  23. }
  24. })
  25. const { PythonCodeRuntime } = await import('../src/index.ts')
  26. it('seals stray fragments without recopying the sealed prefix', async () => {
  27. const ctx = new Context()
  28. const fiber = await ctx.plugin(PythonCodeRuntime, { maxLogBytes: 200_000, maxWallMs: 30_000 })
  29. const realConcat = Buffer.concat.bind(Buffer)
  30. let copied = 0
  31. let maxFragments = 0
  32. const concat = vi.spyOn(Buffer, 'concat').mockImplementation((list, total) => {
  33. maxFragments = Math.max(maxFragments, list.length)
  34. for (const part of list) copied += part.length
  35. return realConcat(list, total)
  36. })
  37. try {
  38. const result = await ctx.codeRuntime.run({
  39. program: 'import os\nos.write(1, b"x" * 60000 + b"\\n")\nreturn "done"',
  40. bindings: [],
  41. })
  42. expect(result.error).toBeUndefined()
  43. expect(result.value).toBe('done')
  44. expect(result.logs).toEqual(['x'.repeat(60_000)])
  45. // Sealing copies each byte at most twice; merging every accumulated prefix
  46. // instead copies over a megabyte for these 60,001 controlled fragments.
  47. expect(maxFragments).toBeLessThanOrEqual(1024)
  48. expect(copied).toBeLessThan(256 * 1024)
  49. } finally {
  50. concat.mockRestore()
  51. await fiber.dispose()
  52. }
  53. }, 40_000)