const assert = require('node:assert'); const { spawnSync } = require('node:child_process'); const fs = require('node:fs'); const os = require('node:os'); const path = require('node:path'); const ant = path.resolve(process.execPath); const buildDir = path.dirname(ant); const repoRoot = path.dirname(buildDir); const runtime = path.join(buildDir, 'ant-runtime'); const fixture = path.join(repoRoot, 'tests', 'fixtures', 'compile-app', 'index.ts'); if (!fs.existsSync(runtime)) { console.log(`skip: ${runtime} not built (ninja -C build ant-runtime)`); process.exit(0); } const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'ant-compile-')); try { const out = path.join(tmp, 'app'); let r = spawnSync(ant, ['compile', '--runtime', runtime, '-o', out, fixture], { encoding: 'utf8' }); assert.equal(r.status, 0, `compile failed: ${r.stderr}`); assert.ok(fs.existsSync(out), 'output binary missing'); r = spawnSync(out, ['a', 'b'], { encoding: 'utf8', cwd: os.homedir() }); assert.equal(r.status, 0, `compiled app failed: ${r.stderr}`); const stdout = r.stdout; assert.ok(stdout.includes('greet: hello world'), stdout); assert.ok(stdout.includes('data: 3'), stdout); assert.ok(stdout.includes('notes: from the vfs'), stdout); assert.ok(stdout.includes('pad: ---x'), stdout); assert.ok(stdout.includes('cjs: legacy-7'), stdout); assert.ok(stdout.includes('argv: ["a","b"]'), stdout); assert.ok(stdout.includes(`execPath: ${fs.realpathSync(out)}`), stdout); assert.ok(stdout.includes('dirname: /$ant'), stdout); assert.ok(stdout.includes(`version: ${JSON.stringify([Ant.version, 'string', Ant.channel])}`), stdout); const versionEnv = { ...process.env, ANT_NO_VERSION_CHECK: '1' }; const antVersion = spawnSync(ant, ['--version'], { encoding: 'utf8', env: versionEnv }); assert.equal(antVersion.status, 0, antVersion.stderr); r = spawnSync(out, ['--ant-version'], { encoding: 'utf8', env: versionEnv }); assert.equal(r.status, 0, r.stderr); assert.equal(r.stdout, antVersion.stdout); const antVersionRaw = spawnSync(ant, ['--version-raw'], { encoding: 'utf8' }); assert.equal(antVersionRaw.status, 0, antVersionRaw.stderr); r = spawnSync(out, ['--ant-version-raw'], { encoding: 'utf8' }); assert.equal(r.status, 0, r.stderr); assert.equal(r.stdout, antVersionRaw.stdout); const antChannel = spawnSync(ant, ['--version-channel'], { encoding: 'utf8' }); assert.equal(antChannel.status, 0, antChannel.stderr); assert.equal(antChannel.stdout, `${Ant.channel}\n`); r = spawnSync(out, ['--ant-version-channel'], { encoding: 'utf8' }); assert.equal(r.status, 0, r.stderr); assert.equal(r.stdout, antChannel.stdout); r = spawnSync(out, ['--throw'], { encoding: 'utf8', cwd: os.homedir() }); assert.equal(r.status, 1, `unhandled TLA rejection exits 1, got ${r.status}`); assert.match(r.stderr, /\/\$ant\/lib\/util\.ts:\d+:\d+/, r.stderr); assert.match(r.stderr, /kaboom/, r.stderr); r = spawnSync(out, ['--fork'], { encoding: 'utf8', cwd: os.homedir() }); assert.equal(r.status, 0, r.stderr); assert.ok(r.stdout.includes('fork exit: 0'), r.stdout); r = spawnSync(out, ['--worker'], { encoding: 'utf8', cwd: os.homedir() }); assert.equal(r.status, 0, r.stderr); assert.ok(r.stdout.includes('worker said: worker-ok:5'), r.stdout); assert.ok(r.stdout.includes('worker exit: 0'), r.stdout); r = spawnSync(out, ['--worker-relative'], { encoding: 'utf8', cwd: os.homedir() }); assert.equal(r.status, 0, r.stderr); assert.ok(r.stdout.includes('worker said: worker-ok:7'), r.stdout); r = spawnSync(runtime, [], { encoding: 'utf8' }); assert.equal(r.status, 1); assert.match(r.stderr, /no embedded program/, r.stderr); } finally { fs.rmSync(tmp, { recursive: true, force: true }); }