loader-smoke.spec.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  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. // macOS realpaths temp dirs into /private; TMPDIR may live under /var or /tmp.
  11. const canonicalTempPath = (path: string): string => path.replace(/^\/private(?=\/(?:var|tmp)\/)/, '')
  12. describe('runLoaderSmoke', () => {
  13. it('isolates the process, closes stdin, captures output, and removes the cwd', async () => {
  14. const result = await runLoaderSmoke({
  15. label: 'success fixture',
  16. tempDirPrefix: 'loader-smoke-success-',
  17. binScript: fixture('success'),
  18. configPath,
  19. tsconfigPath,
  20. mode: 'src',
  21. env: { LOADER_SMOKE_MARKER: 'present' },
  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: '',
  37. })
  38. expect(canonicalTempPath(output.dshHome)).toBe(canonicalTempPath(join(output.cwd, '.dsh')))
  39. expect(canonicalTempPath(output.agentsHome)).toBe(canonicalTempPath(join(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 (expected 0). stdout:\n\nstderr:\nfixture failed')
  75. })
  76. it('accepts a declared expected failure exit and rejects any other outcome', async () => {
  77. // A scenario pinning a designed failure surface declares its exit code…
  78. const declared = await runLoaderSmoke({
  79. label: 'declared failure fixture',
  80. tempDirPrefix: 'loader-smoke-declared-fail-',
  81. binScript: fixture('fail'),
  82. libBinScript: fixture('fail'),
  83. configPath,
  84. tsconfigPath,
  85. expectedExitCode: 7,
  86. })
  87. expect(declared.stderr).toBe('fixture failed\n')
  88. // …and a run that succeeds instead still fails the smoke.
  89. await expect(runLoaderSmoke({
  90. label: 'unexpectedly clean fixture',
  91. tempDirPrefix: 'loader-smoke-clean-',
  92. binScript: fixture('success'),
  93. libBinScript: fixture('success'),
  94. configPath,
  95. tsconfigPath,
  96. expectedExitCode: 7,
  97. })).rejects.toThrow(/exited 0 \(expected 7\)/)
  98. })
  99. it('kills a process at its deadline and reports captured output', async () => {
  100. await expect(runLoaderSmoke({
  101. label: 'hanging fixture',
  102. tempDirPrefix: 'loader-smoke-hang-',
  103. binScript: fixture('hang'),
  104. libBinScript: fixture('hang'),
  105. configPath,
  106. tsconfigPath,
  107. processTimeoutMs: 100,
  108. })).rejects.toThrow('hanging fixture did not exit within 0.1s.')
  109. })
  110. })