Path: blob/main/src/vs/sessions/contrib/chat/test/browser/resolveRemoteAuthority.test.ts
13405 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import assert from 'assert';6import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';7import { getEntryAddress, IRemoteAgentHostEntry, IRemoteAgentHostService, RemoteAgentHostEntryType } from '../../../../../platform/agentHost/common/remoteAgentHostService.js';8import { ISessionsProvidersService } from '../../../../services/sessions/browser/sessionsProvidersService.js';9import { resolveRemoteAuthority, sshAuthorityString } from '../../browser/openInVSCodeUtils.js';10import { decodeHex } from '../../../../../base/common/buffer.js';1112suite('resolveRemoteAuthority', () => {1314ensureNoDisposablesAreLeakedInTestSuite();1516function makeProvidersService(remoteAddress?: string): ISessionsProvidersService {17return {18getProvider: (id: string) => remoteAddress ? { id, remoteAddress } : undefined,19} as unknown as ISessionsProvidersService; // no-as-any justification: lightweight test mock for a multi-method service interface20}2122function makeRemoteAgentHostService(entries: IRemoteAgentHostEntry[] = []): IRemoteAgentHostService {23return {24getEntryByAddress: (address: string) => entries.find(e => getEntryAddress(e) === address),25} as unknown as IRemoteAgentHostService; // no-as-any justification: lightweight test mock for a multi-method service interface26}2728test('returns undefined for a local provider', () => {29const result = resolveRemoteAuthority(30'local-provider',31makeProvidersService(undefined) as ISessionsProvidersService,32makeRemoteAgentHostService() as IRemoteAgentHostService,33);34assert.strictEqual(result, undefined);35});3637test('returns undefined when provider has no remoteAddress', () => {38const noRemoteProviders = {39getProvider: (id: string) => ({ id /* no remoteAddress */ }),40} as unknown as ISessionsProvidersService; // no-as-any justification: lightweight test mock for a multi-method service interface41const result = resolveRemoteAuthority(42'agenthost-no-address',43noRemoteProviders,44makeRemoteAgentHostService() as IRemoteAgentHostService,45);46assert.strictEqual(result, undefined);47});4849test('returns ssh-remote authority for SSH with sshConfigHost', () => {50const result = resolveRemoteAuthority(51'agenthost-myserver',52makeProvidersService('localhost:4321') as ISessionsProvidersService,53makeRemoteAgentHostService([{54name: 'My Server',55connection: {56type: RemoteAgentHostEntryType.SSH,57address: 'localhost:4321',58sshConfigHost: 'my-ssh-host',59hostName: 'myserver.example.com',60},61}]) as IRemoteAgentHostService,62);63assert.strictEqual(result, 'ssh-remote+my-ssh-host');64});6566test('returns ssh-remote with simple hostName for SSH without sshConfigHost', () => {67const result = resolveRemoteAuthority(68'agenthost-myserver',69makeProvidersService('localhost:4321') as ISessionsProvidersService,70makeRemoteAgentHostService([{71name: 'My Server',72connection: {73type: RemoteAgentHostEntryType.SSH,74address: 'localhost:4321',75hostName: 'myserver',76},77}]) as IRemoteAgentHostService,78);79assert.strictEqual(result, 'ssh-remote+myserver');80});8182test('returns ssh-remote with hex-encoded authority for SSH with user and port', () => {83const result = resolveRemoteAuthority(84'agenthost-myserver',85makeProvidersService('localhost:4321') as ISessionsProvidersService,86makeRemoteAgentHostService([{87name: 'My Server',88connection: {89type: RemoteAgentHostEntryType.SSH,90address: 'localhost:4321',91hostName: 'myserver.example.com',92user: 'admin',93port: 2222,94},95}]) as IRemoteAgentHostService,96);97assert.ok(result?.startsWith('ssh-remote+'));98// The authority should be hex-encoded JSON99const authority = result!.slice('ssh-remote+'.length);100const decoded = decodeHex(authority).toString();101assert.deepStrictEqual(JSON.parse(decoded), {102hostName: 'myserver.example.com',103user: 'admin',104port: 2222,105});106});107108test('returns tunnel authority using label', () => {109const result = resolveRemoteAuthority(110'agenthost-tunnel',111makeProvidersService('tunnel:myTunnelId') as ISessionsProvidersService,112makeRemoteAgentHostService([{113name: 'My Tunnel',114connection: {115type: RemoteAgentHostEntryType.Tunnel,116tunnelId: 'myTunnelId',117clusterId: 'usw2',118label: 'my-machine',119},120}]) as IRemoteAgentHostService,121);122assert.strictEqual(result, 'tunnel+my-machine');123});124125test('returns tunnel authority falling back to tunnelId when no label', () => {126const result = resolveRemoteAuthority(127'agenthost-tunnel',128makeProvidersService('tunnel:myTunnelId') as ISessionsProvidersService,129makeRemoteAgentHostService([{130name: 'My Tunnel',131connection: {132type: RemoteAgentHostEntryType.Tunnel,133tunnelId: 'myTunnelId',134clusterId: 'usw2',135},136}]) as IRemoteAgentHostService,137);138assert.strictEqual(result, 'tunnel+myTunnelId.usw2');139});140141test('returns undefined for WebSocket connections', () => {142const result = resolveRemoteAuthority(143'agenthost-ws',144makeProvidersService('myhost:4321') as ISessionsProvidersService,145makeRemoteAgentHostService([{146name: 'WS Host',147connection: {148type: RemoteAgentHostEntryType.WebSocket,149address: 'myhost:4321',150},151}]) as IRemoteAgentHostService,152);153assert.strictEqual(result, undefined);154});155156test('returns undefined when no matching entry found', () => {157const result = resolveRemoteAuthority(158'agenthost-missing',159makeProvidersService('unknown-address:9999') as ISessionsProvidersService,160makeRemoteAgentHostService([{161name: 'Other',162connection: {163type: RemoteAgentHostEntryType.WebSocket,164address: 'different-address:1234',165},166}]) as IRemoteAgentHostService,167);168assert.strictEqual(result, undefined);169});170});171172suite('sshAuthorityString', () => {173174ensureNoDisposablesAreLeakedInTestSuite();175176test('hex-encodes when user is present', () => {177const result = sshAuthorityString({178type: RemoteAgentHostEntryType.SSH,179address: 'localhost:4321',180hostName: 'myserver',181user: 'admin',182});183const decoded = decodeHex(result).toString();184assert.deepStrictEqual(JSON.parse(decoded), { hostName: 'myserver', user: 'admin' });185});186187test('hex-encodes when port is present', () => {188const result = sshAuthorityString({189type: RemoteAgentHostEntryType.SSH,190address: 'localhost:4321',191hostName: 'myserver',192port: 2222,193});194const decoded = decodeHex(result).toString();195assert.deepStrictEqual(JSON.parse(decoded), { hostName: 'myserver', port: 2222 });196});197198test('hex-encodes when hostName has uppercase letters', () => {199const result = sshAuthorityString({200type: RemoteAgentHostEntryType.SSH,201address: 'localhost:4321',202hostName: 'MyServer',203});204const decoded = decodeHex(result).toString();205assert.deepStrictEqual(JSON.parse(decoded), { hostName: 'MyServer' });206});207208test('hex-encodes with all fields', () => {209const result = sshAuthorityString({210type: RemoteAgentHostEntryType.SSH,211address: 'localhost:4321',212hostName: 'MyServer.example.com',213user: 'root',214port: 22,215});216const decoded = decodeHex(result).toString();217assert.deepStrictEqual(JSON.parse(decoded), {218hostName: 'MyServer.example.com',219user: 'root',220port: 22,221});222});223224test('uses hostName directly when address differs', () => {225const result = sshAuthorityString({226type: RemoteAgentHostEntryType.SSH,227address: 'localhost:4321',228hostName: 'actualhost',229});230assert.strictEqual(result, 'actualhost');231});232});233234235