56 lines
3.1 KiB
JavaScript
56 lines
3.1 KiB
JavaScript
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})}
|
|
})
|