const { test } = require('node:test') const assert = require('node:assert/strict') const fs = require('node:fs') const vm = require('node:vm') const ts = require('typescript') const React = require('react') const { renderToStaticMarkup } = require('react-dom/server') function load(file, overrides = {}, globals = {}) { const exports = {} vm.runInNewContext(ts.transpileModule(fs.readFileSync(require.resolve(file), 'utf8'), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, jsx: ts.JsxEmit.ReactJSX } }).outputText, { exports, process, require: name => overrides[name] ?? require(name), ...globals }) return exports } const shared = load('../src/shared/remoteLatency.ts') const main = load('../src/main/remoteLatency.ts') const { createRemoteLatencyMonitor } = load('../src/renderer/src/features/platforms/remoteLatencyMonitor.ts', { '../../../../shared/remoteLatency': shared }) const i18n = { t: key => key, useLocaleRender() {} } const { default: RemoteLatencyLabel } = load('../src/renderer/src/components/RemoteLatencyLabel.tsx', { '../i18n': i18n, '../../../shared/remoteLatency': shared }) const plain = value => JSON.parse(JSON.stringify(value)) const tick = () => new Promise(resolve => setImmediate(resolve)) const deferred = () => { let resolve; const promise = new Promise(done => { resolve = done }); return { promise, resolve } } test('ping targets cannot inject commands or options and accept real host formats', () => { for (const host of ['127.0.0.1', '100.64.0.10', 'mk-mini.example.com', 'jetson', '::1', '[2001:db8::1]']) assert.ok(main.remoteLatencyHost(host)) for (const host of [null, {}, '', '-f', '--help', 'host; echo BAD', 'host\nother', 'ssh://host:22', 'a'.repeat(254), 'user@host', 'a..b', '/tmp/file']) { assert.throws(() => main.remoteLatencyHost(host), /Invalid/) } assert.equal(main.remoteLatencyHost('[::1]'), '::1') assert.deepEqual(plain(main.remoteLatencyPingArgs('host', 'linux')), ['-n', '-c', '1', '-W', '2', '--', 'host']) assert.deepEqual(plain(main.remoteLatencyPingArgs('host', 'win32')), ['-n', '1', '-w', '2000', 'host']) assert.deepEqual(plain(main.remoteLatencyPingArgs('host', 'darwin')), ['-n', '-c', '1', '-W', '2000', '--', 'host']) }) test('parses actual echo time, not process duration or packet loss', () => { for (const [output, expected] of [ ['64 bytes from device: icmp_seq=1 ttl=64 time=42.5 ms', 42.5], ['Reply from host: bytes=32 time<1ms TTL=128', 0.5], ['응답: 바이트=32 시간=12ms TTL=128', 12], ['Reply: time=42,5 ms', 42.5], ['100% packet loss, time 2000ms', null], ['Request timed out.', null] ]) assert.equal(main.parseRemoteLatency(output), expected) }) test('runs one bounded ping without a shell and returns null on missing binary or timeout', async () => { for (const error of [null, Error('ENOENT'), Error('timeout')]) { const mock = load('../src/main/remoteLatency.ts', { 'node:child_process': { execFile: (binary, args, options, callback) => { assert.equal(binary, 'ping') assert.equal(options.shell, undefined) assert.equal(options.timeout, 2500) assert.equal(options.maxBuffer, 8192) assert.equal(options.windowsHide, true) assert.equal(options.env.LC_ALL, 'C') assert.equal(args.at(-1), '127.0.0.1') callback(error, 'time=42 ms') } } }) assert.equal(await mock.measureRemoteLatency('127.0.0.1'), error ? null : 42) } }) function harness(read) { const timers = new Map() let id = 0 const monitor = createRemoteLatencyMonitor(read, { setInterval: (callback, interval) => { assert.equal(interval, 5000); timers.set(++id, callback); return id }, clearInterval: id => timers.delete(id) }) return { monitor, timers, sample: async () => { [...timers.values()].forEach(callback => callback()); await tick() } } } test('shares each host probe across displays and uses only the last three samples', async () => { const values = [40, 1800, 42, 50] let calls = 0 const h = harness(async () => { calls++; return values.shift() }) h.monitor.setHosts(['jetson', 'jetson']) assert.equal(h.monitor.getSnapshot().jetson.status, 'measuring') await tick() assert.equal(h.timers.size, 1) assert.equal(calls, 1) assert.equal(h.monitor.getSnapshot().jetson.milliseconds, 40) await h.sample() await h.sample() assert.equal(h.monitor.getSnapshot().jetson.milliseconds, 42) await h.sample() assert.equal(h.monitor.getSnapshot().jetson.milliseconds, 50) h.monitor.stop() assert.equal(h.timers.size, 0) }) test('does not overlap slow probes and ignores completions after disconnect or host reuse', async () => { const old = deferred(), next = deferred() let calls = 0 const h = harness(() => ++calls === 1 ? old.promise : next.promise) h.monitor.setHosts(['jetson']) await h.sample() assert.equal(calls, 1) h.monitor.setHosts([]) h.monitor.setHosts(['jetson']) assert.equal(calls, 2) old.resolve(999) await tick() assert.equal(h.monitor.getSnapshot().jetson.status, 'measuring') next.resolve(42) await tick() assert.equal(h.monitor.getSnapshot().jetson.milliseconds, 42) h.monitor.stop() assert.deepEqual(plain(h.monitor.getSnapshot()), {}) }) test('clears stale success immediately after failure and starts a fresh sample window on recovery', async () => { const values = [40, 50, null, 350] const h = harness(async () => values.shift()) h.monitor.setHosts(['jetson']) await tick() await h.sample() await h.sample() assert.deepEqual(plain(h.monitor.getSnapshot().jetson), { milliseconds: null, status: 'unavailable' }) await h.sample() assert.equal(h.monitor.getSnapshot().jetson.milliseconds, 350) h.monitor.stop() }) test('adding another target preserves existing samples and removing it stops its probe', async () => { const h = harness(async host => host === 'a' ? 42 : 200) h.monitor.setHosts(['a']) await tick() const before = h.monitor.getSnapshot().a h.monitor.setHosts(['a', 'b']) assert.equal(h.monitor.getSnapshot().a, before) await tick() assert.equal(h.timers.size, 2) h.monitor.setHosts(['a']) assert.equal(h.timers.size, 1) assert.equal(h.monitor.getSnapshot().b, undefined) h.monitor.stop() }) test('shows only stable-width milliseconds with the requested colors in both themes', () => { for (const dark of [false, true]) { for (const [milliseconds, tone] of [[42, 'good'], [100, 'good'], [101, 'warning'], [250, 'warning'], [251, 'poor']]) { const latency = { milliseconds, status: 'ok' } assert.equal(shared.remoteLatencyTone(latency), tone) const html = renderToStaticMarkup(React.createElement(RemoteLatencyLabel, { latency, dark })) assert.ok(html.includes(`>${milliseconds} ms`)) assert.match(html, /w-\[48px\]/) assert.match(html, /tabular-nums/) assert.ok(html.includes(tone === 'good' ? dark ? '#4ade80' : '#15803d' : tone === 'warning' ? dark ? '#facc15' : '#a16207' : dark ? '#f87171' : '#dc2626')) } } assert.equal(renderToStaticMarkup(React.createElement(RemoteLatencyLabel)), '') assert.equal(shared.remoteLatencyText({ milliseconds: 0.02, status: 'ok' }), '1 ms') for (const status of ['measuring', 'unavailable']) { const latency = { milliseconds: null, status } assert.match(renderToStaticMarkup(React.createElement(RemoteLatencyLabel, { latency })), />-- ms<\/span>/) assert.equal(shared.remoteLatencyTone(latency), status === 'measuring' ? 'unknown' : 'poor') } }) test('sidebar and countdown header use the same label while local platforms have no measurement', () => { const overrides = { '../../i18n': i18n, '../i18n': i18n, '../../components/RemoteLatencyLabel': { default: RemoteLatencyLabel }, './RemoteLatencyLabel': { default: RemoteLatencyLabel }, '../../components/Tooltip': { default: ({ children }) => children } } const { default: TopBar } = load('../src/renderer/src/features/workspace/WorkspaceTopBar.tsx', overrides) const { default: Sidebar } = load('../src/renderer/src/components/Sidebar.tsx', { ...overrides, react: { ...React, useState: () => [false, () => {}], useRef: () => ({ current: null }), useEffect() {} } }) const latency = { milliseconds: 42, status: 'ok' } const header = renderToStaticMarkup(React.createElement(TopBar, { platformName: 'MK-mini', remoteLatency: latency, showControlCountdown: true, formatControlRemainingTime: () => '27:13', topToggleButtonClass: () => '', dark: true })) const sidebar = renderToStaticMarkup(Sidebar({ collapsed: false, onToggle() {}, sessionStatus: 'running', runningSessions: [{ id: 'remote', title: 'MK-mini', latency }, { id: 'local', title: 'Local PC' }] })) assert.match(header, /27:13/) assert.equal((header.match(/>42 ms<\/span>/g) ?? []).length, 1) assert.equal((sidebar.match(/>42 ms<\/span>/g) ?? []).length, 1) const appSource = fs.readFileSync(require.resolve('../src/renderer/src/App.tsx'), 'utf8') assert.match(appSource, /platform\.platformKey !== 'futuredrive-local-pc'/) assert.match(appSource, /remoteLatency=\{getRemotePlatformLatency\(workspacePlatform\)\}/) assert.match(appSource, /latency: getRemotePlatformLatency\(platform\)/) })