const { test } = require('node:test') const assert = require('node:assert/strict') const fs = require('node:fs') const path = require('node:path') const ts = require('typescript') const source = ts.createSourceFile('index.ts', fs.readFileSync(path.join(__dirname, '../src/main/index.ts'), 'utf8'), ts.ScriptTarget.Latest, true) const names = ['buildFastDdsPeerConfig', 'parseCameraLanAddresses', 'cameraLanEnabled', 'rosNetworkEnabled', 'prepareRemoteRosNetworkConfig'] const code = source.statements.filter(node => ts.isFunctionDeclaration(node) && names.includes(node.name?.text)).map(node => node.getText(source)).join('\n') function load(overrides = {}) { const dependencies = { parseRosDomainId: value => Number(value ?? 0), readLocalTailscaleIpv4: async () => '100.64.0.10', readRemoteTailscaleIpv4: async () => '100.64.0.20', runSshOutput: async () => JSON.stringify([{ addr_info: [{ family: 'inet', scope: 'global', local: '192.168.1.20' }] }]), runSsh: async () => {}, quoteShellSingle: value => "'" + value.replaceAll("'", "'\\''") + "'", expandRemotePathVar: () => [], encodeBase64: value => Buffer.from(value).toString('base64'), ...overrides, } return new Function(...Object.keys(dependencies), ts.transpile(code, { target: ts.ScriptTarget.ES2022 }) + `;return {${names.join(',')}}`)(...Object.values(dependencies)) } test('LAN discovery adds physical addresses and multicast while keeping Tailscale peers', () => { const { buildFastDdsPeerConfig } = load() const xml = buildFastDdsPeerConfig('100.64.0.10', '100.64.0.20', '77', ['192.168.1.20']) const whitelist = xml.match(/(.*?)<\/interfaceWhiteList>/s)[1] for (const address of ['127.0.0.1', '100.64.0.20', '192.168.1.20']) assert.ok(whitelist.includes(address)) assert.ok(xml.includes('
100.64.0.10
')) assert.ok(xml.includes('
239.255.0.1
26650')) assert.ok(xml.includes('')) const original = buildFastDdsPeerConfig('100.64.0.10', '100.64.0.20', '77') assert.ok(!original.includes('192.168.1.20')) assert.ok(!original.includes('239.255.0.1')) }) test('only the Yahboom camera opts in', () => { const { cameraLanEnabled } = load() assert.equal(cameraLanEnabled('[lms-nav2-yahboom-camera]yahboom_camera_v1.0.0_ws'), true) for (const role of ['vehicle', 'agent', 'control', 'slam', 'planning']) { assert.equal(cameraLanEnabled(`[lms-nav2-yahboom-${role}]yahboom_${role}_v1.0.0_ws`), false) } assert.equal(cameraLanEnabled('[lms-nav2-custom]camera_v1.0.0_ws'), false) }) test('physical interface responses are parsed, validated and deduplicated', () => { const { parseCameraLanAddresses } = load() const output = JSON.stringify([{ addr_info: [ { family: 'inet', scope: 'global', local: '192.168.1.20' }, { family: 'inet', scope: 'global', local: '999.1.1.1' }, { family: 'inet6', scope: 'global', local: 'fe80::1' }, ] }]) assert.deepEqual(parseCameraLanAddresses(output + '\n' + output), ['192.168.1.20']) }) test('camera config uses its own path and LAN works without ROS platform linking', async () => { let script = '' const api = load({ readLocalTailscaleIpv4: async () => { throw new Error('Must not require local Tailscale') }, readRemoteTailscaleIpv4: async () => { throw new Error('Must not require remote Tailscale') }, runSsh: async (_target, command) => { script = command }, }) assert.equal(await api.prepareRemoteRosNetworkConfig({}, '/runtime', { enabled: false }, '77'), null) const result = await api.prepareRemoteRosNetworkConfig({}, '/runtime', { enabled: false }, '77', true) assert.ok(result.endsWith('-camera-lan.xml')) const encoded = script.match(/printf %s '([^']+)'/)[1] const xml = Buffer.from(encoded, 'base64').toString() assert.ok(xml.includes('192.168.1.20')) assert.ok(xml.includes('239.255.0.1')) }) test('linked camera retains both networks and does not overwrite restricted config', async () => { const api = load() const restricted = await api.prepareRemoteRosNetworkConfig({}, '/runtime', { enabled: true }, '77') const camera = await api.prepareRemoteRosNetworkConfig({}, '/runtime', { enabled: true }, '77', true) assert.notEqual(camera, restricted) assert.ok(camera.includes('100-64-0-10')) const noLan = load({ runSshOutput: async () => '' }) await assert.rejects(noLan.prepareRemoteRosNetworkConfig({}, '/runtime', { enabled: true }, '77', true), /IPv4/) })