loader-smoke.spec.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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, closes 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. })
  22. const output = JSON.parse(result.stdout) as {
  23. configPath: string
  24. args: string[]
  25. cwd: string
  26. dshHome: string
  27. agentsHome: string
  28. marker: string
  29. input: string
  30. }
  31. expect(output).toMatchObject({
  32. configPath,
  33. args: [configPath],
  34. marker: 'present',
  35. input: '',
  36. })
  37. expect(canonicalTempPath(output.dshHome)).toBe(canonicalTempPath(join(output.cwd, '.dsh')))
  38. expect(canonicalTempPath(output.agentsHome)).toBe(canonicalTempPath(join(output.cwd, '.agents')))
  39. expect(result.stderr).toContain('fixture stderr')
  40. expect(existsSync(output.cwd)).toBe(false)
  41. }, LOADER_SMOKE_TEST_TIMEOUT_MS)
  42. it('passes an arbitrary bin argv and inspects world state before cleanup', async () => {
  43. let inspected = ''
  44. let marker = ''
  45. const result = await runLoaderSmoke({
  46. label: 'argv fixture',
  47. tempDirPrefix: 'loader-smoke-argv-',
  48. binScript: fixture('success'),
  49. libBinScript: fixture('success'),
  50. configPath,
  51. binArgs: ['--config', configPath, '--output-format', 'json', 'task with spaces'],
  52. tsconfigPath,
  53. prepare: cwd => writeFile(join(cwd, 'marker.txt'), 'prepared'),
  54. inspect: async (cwd) => {
  55. inspected = cwd
  56. marker = await readFile(join(cwd, 'marker.txt'), 'utf8')
  57. },
  58. })
  59. const output = JSON.parse(result.stdout) as { args: string[]; cwd: string }
  60. expect(output.args).toEqual(['--config', configPath, '--output-format', 'json', 'task with spaces'])
  61. expect(canonicalTempPath(inspected)).toBe(canonicalTempPath(output.cwd))
  62. expect(marker).toBe('prepared')
  63. expect(existsSync(inspected)).toBe(false)
  64. }, LOADER_SMOKE_TEST_TIMEOUT_MS)
  65. it('rejects a non-zero exit with captured diagnostics', async () => {
  66. await expect(runLoaderSmoke({
  67. label: 'failure fixture',
  68. tempDirPrefix: 'loader-smoke-fail-',
  69. binScript: fixture('fail'),
  70. libBinScript: fixture('fail'),
  71. configPath,
  72. tsconfigPath,
  73. })).rejects.toThrow('failure fixture exited 7 (expected 0). stdout:\n\nstderr:\nfixture failed')
  74. })
  75. it('accepts a declared expected failure exit and rejects any other outcome', async () => {
  76. // A scenario pinning a designed failure surface declares its exit code…
  77. const declared = await runLoaderSmoke({
  78. label: 'declared failure fixture',
  79. tempDirPrefix: 'loader-smoke-declared-fail-',
  80. binScript: fixture('fail'),
  81. libBinScript: fixture('fail'),
  82. configPath,
  83. tsconfigPath,
  84. expectedExitCode: 7,
  85. })
  86. expect(declared.stderr).toBe('fixture failed\n')
  87. // …and a run that succeeds instead still fails the smoke.
  88. await expect(runLoaderSmoke({
  89. label: 'unexpectedly clean fixture',
  90. tempDirPrefix: 'loader-smoke-clean-',
  91. binScript: fixture('success'),
  92. libBinScript: fixture('success'),
  93. configPath,
  94. tsconfigPath,
  95. expectedExitCode: 7,
  96. })).rejects.toThrow(/exited 0 \(expected 7\)/)
  97. })
  98. it('kills a process at its deadline and reports captured output', async () => {
  99. await expect(runLoaderSmoke({
  100. label: 'hanging fixture',
  101. tempDirPrefix: 'loader-smoke-hang-',
  102. binScript: fixture('hang'),
  103. libBinScript: fixture('hang'),
  104. configPath,
  105. tsconfigPath,
  106. processTimeoutMs: 100,
  107. })).rejects.toThrow('hanging fixture did not exit within 0.1s.')
  108. })
  109. })