const {test} = require('node:test') const assert = require('node:assert/strict') const fs = require('node:fs/promises') const path = require('node:path') const os = require('node:os') const vm = require('node:vm') const ts = require('typescript') const {createHash} = require('node:crypto') const {spawnSync} = require('node:child_process') test('remote visualization stages the bundled bridge over stdin and mounts that revision read-only', async () => { const source = ts.createSourceFile('index.ts', await fs.readFile(path.join(__dirname, '../src/main/index.ts'), 'utf8'), ts.ScriptTarget.Latest, true) const fn = source.statements.find(node => ts.isFunctionDeclaration(node) && node.name?.text === 'startRemoteVisualizationBridge') assert.ok(fn) const dir = await fs.mkdtemp(path.join(os.tmpdir(), 'lms-camera-bridge-')) const resource = path.resolve(__dirname, '../resources/slam-ros-bridge') const quote = value => "'" + value.replaceAll("'", "'\\''") + "'" let launch, transfers = 0 const context = { normalizeVisualizationStack: () => 'slam3d', normalizeRemoteTarget: target => target, prepareRemoteRosNetworkConfig: async () => null, visualizationBridgeContainerName: () => 'slam-ros-bridge', resolveVisualizationBridgeImage: () => 'fixture:arm64', bridgeArtifact: () => null, slamRosBridgeImage: 'slam:local', bridgeContainerCommand: () => 'python3 /app/bridge.py', resolveResourceContextPath: () => resource, readFile: fs.readFile, join: path.join, createHash, quoteShellSingle: quote, expandRemotePathVar: () => [], reportVisualizationProgress() {}, runUnqueuedSshOutput: async (_target, command, timeout, input) => { transfers++ assert.equal(timeout, 30000) assert.ok(input.length > 1000) const {spawn} = require('node:child_process') await new Promise((resolve, reject) => { const child = spawn('bash', ['-c', command], {env: {...process.env, HOME: dir}, stdio:['pipe','ignore','pipe']}) let error = '' child.stderr.on('data', data => {error += data}) child.on('error', reject) child.on('close', code => code === 0 ? resolve() : reject(Error(error))) child.stdin.end(input) }) return '' }, runSsh: async (_target, command) => { launch = command } } vm.runInNewContext(ts.transpileModule(fn.getText(source), {compilerOptions:{target:ts.ScriptTarget.ES2022}}).outputText, context) try { await context.startRemoteVisualizationBridge({workspaceRoot:'/workspace'}, 'slam3d', '77') assert.equal(transfers, 1) assert.match(launch, /-v "\$HOME\/\.autonomy-studio\/runtime\/bridges\/[a-f0-9]{64}:\/app:ro"/) const roots = await fs.readdir(path.join(dir, '.autonomy-studio/runtime/bridges')) for (const name of ['bridge.py','requirements.txt']) assert.equal(await fs.readFile(path.join(dir,'.autonomy-studio/runtime/bridges',roots[0],name),'utf8'), await fs.readFile(path.join(resource,name),'utf8')) const syntax = spawnSync('bash', ['-n'], {input:launch,encoding:'utf8'}) assert.equal(syntax.status, 0, syntax.stderr) assert.ok(launch.includes('docker run')) } finally {await fs.rm(dir,{recursive:true,force:true})} })