loader-smoke.spec.ts 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import { existsSync } from 'node:fs'
  2. import { readFile, writeFile } from 'node:fs/promises'
  3. import { join } from 'node:path'
  4. import { fileURLToPath } from 'node:url'
  5. import { describe, expect, it } from 'vitest'
  6. import { LOADER_SMOKE_TEST_TIMEOUT_MS, runLoaderSmoke } from '@deepseek-ai/dsh-loader-smoke'
  7. const configPath = '/tmp/fixture.cordis.yml'
  8. const tsconfigPath = fileURLToPath(new URL('../../../../tsconfig.json', import.meta.url))
  9. const fixture = (name: string): string => fileURLToPath(new URL(`./fixtures/${name}.ts`, import.meta.url))
  10. const canonicalTempPath = (path: string): string => path.replace(/^\/private(?=\/var\/)/, '')
  11. describe('runLoaderSmoke', () => {
  12. it('isolates the process, writes stdin, captures output, and removes the cwd', async () => {
  13. const result = await runLoaderSmoke({
  14. label: 'success fixture',
  15. tempDirPrefix: 'loader-smoke-success-',
  16. binScript: fixture('success'),
  17. configPath,
  18. tsconfigPath,
  19. mode: 'src',
  20. env: { LOADER_SMOKE_MARKER: 'present' },
  21. stdinLines: ['one', 'two'],
  22. })
  23. const output = JSON.parse(result.stdout) as {
  24. configPath: string
  25. args: string[]
  26. cwd: string
  27. dshHome: string
  28. agentsHome: string
  29. marker: string
  30. input: string
  31. }
  32. expect(output).toMatchObject({
  33. configPath,
  34. args: [configPath],
  35. marker: 'present',
  36. input: 'one\ntwo\n',
  37. })
  38. expect(canonicalTempPath(output.dshHome)).toBe(`${canonicalTempPath(output.cwd)}/.dsh`)
  39. expect(canonicalTempPath(output.agentsHome)).toBe(`${canonicalTempPath(output.cwd)}/.agents`)
  40. expect(result.stderr).toContain('fixture stderr')
  41. expect(existsSync(output.cwd)).toBe(false)
  42. }, LOADER_SMOKE_TEST_TIMEOUT_MS)
  43. it('passes an arbitrary bin argv and inspects world state before cleanup', async () => {
  44. let inspected = ''
  45. let marker = ''
  46. const result = await runLoaderSmoke({
  47. label: 'argv fixture',
  48. tempDirPrefix: 'loader-smoke-argv-',
  49. binScript: fixture('success'),
  50. libBinScript: fixture('success'),
  51. configPath,
  52. binArgs: ['--config', configPath, '--output-format', 'json', 'task with spaces'],
  53. tsconfigPath,
  54. prepare: cwd => writeFile(join(cwd, 'marker.txt'), 'prepared'),
  55. inspect: async (cwd) => {
  56. inspected = cwd
  57. marker = await readFile(join(cwd, 'marker.txt'), 'utf8')
  58. },
  59. })
  60. const output = JSON.parse(result.stdout) as { args: string[]; cwd: string }
  61. expect(output.args).toEqual(['--config', configPath, '--output-format', 'json', 'task with spaces'])
  62. expect(canonicalTempPath(inspected)).toBe(canonicalTempPath(output.cwd))
  63. expect(marker).toBe('prepared')
  64. expect(existsSync(inspected)).toBe(false)
  65. }, LOADER_SMOKE_TEST_TIMEOUT_MS)
  66. it('rejects a non-zero exit with captured diagnostics', async () => {
  67. await expect(runLoaderSmoke({
  68. label: 'failure fixture',
  69. tempDirPrefix: 'loader-smoke-fail-',
  70. binScript: fixture('fail'),
  71. libBinScript: fixture('fail'),
  72. configPath,
  73. tsconfigPath,
  74. })).rejects.toThrow('failure fixture exited 7. stdout:\n\nstderr:\nfixture failed')
  75. })
  76. it('kills a process at its deadline and reports captured output', async () => {
  77. await expect(runLoaderSmoke({
  78. label: 'hanging fixture',
  79. tempDirPrefix: 'loader-smoke-hang-',
  80. binScript: fixture('hang'),
  81. libBinScript: fixture('hang'),
  82. configPath,
  83. tsconfigPath,
  84. processTimeoutMs: 100,
  85. })).rejects.toThrow('hanging fixture did not exit within 0.1s.')
  86. })
  87. })