Path: blob/main/src/vs/platform/agentHost/test/common/sshConfigParsing.test.ts
13399 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 { parseSSHConfigHostEntries, parseSSHGOutput } from '../../common/sshConfigParsing.js';89suite('SSH Config Parsing', () => {1011ensureNoDisposablesAreLeakedInTestSuite();1213suite('parseSSHConfigHostEntries', () => {1415test('extracts simple host entries', () => {16const config = [17'Host myserver',18' HostName 10.0.0.1',19' User admin',20].join('\n');2122assert.deepStrictEqual(parseSSHConfigHostEntries(config), ['myserver']);23});2425test('extracts multiple hosts from a single Host line', () => {26const config = 'Host server1 server2 server3';27assert.deepStrictEqual(parseSSHConfigHostEntries(config), ['server1', 'server2', 'server3']);28});2930test('extracts hosts from multiple Host directives', () => {31const config = [32'Host work',33' HostName work.example.com',34'',35'Host personal',36' HostName home.example.com',37].join('\n');3839assert.deepStrictEqual(parseSSHConfigHostEntries(config), ['work', 'personal']);40});4142test('skips wildcard hosts', () => {43const config = [44'Host *',45' ForwardAgent yes',46'',47'Host myserver',48' HostName 10.0.0.1',49'',50'Host *.example.com',51' User admin',52].join('\n');5354assert.deepStrictEqual(parseSSHConfigHostEntries(config), ['myserver']);55});5657test('skips negation patterns', () => {58const config = 'Host !internal myserver';59assert.deepStrictEqual(parseSSHConfigHostEntries(config), ['myserver']);60});6162test('skips question mark wildcards', () => {63const config = 'Host server? myserver';64assert.deepStrictEqual(parseSSHConfigHostEntries(config), ['myserver']);65});6667test('skips comment lines', () => {68const config = [69'# This is a comment',70'Host myserver',71' # Another comment',72' HostName 10.0.0.1',73].join('\n');7475assert.deepStrictEqual(parseSSHConfigHostEntries(config), ['myserver']);76});7778test('strips inline comments from Host values', () => {79const config = 'Host myserver # my favorite server';80assert.deepStrictEqual(parseSSHConfigHostEntries(config), ['myserver']);81});8283test('handles empty content', () => {84assert.deepStrictEqual(parseSSHConfigHostEntries(''), []);85});8687test('handles content with only comments and blanks', () => {88const config = [89'# comment',90'',91' # indented comment',92'',93].join('\n');9495assert.deepStrictEqual(parseSSHConfigHostEntries(config), []);96});9798test('is case-insensitive for Host keyword', () => {99const config = [100'host lower',101'HOST upper',102'Host mixed',103].join('\n');104105assert.deepStrictEqual(parseSSHConfigHostEntries(config), ['lower', 'upper', 'mixed']);106});107108test('ignores non-Host directives', () => {109const config = [110'Host myserver',111' HostName 10.0.0.1',112' User admin',113' Port 2222',114' IdentityFile ~/.ssh/mykey',115' ForwardAgent yes',116].join('\n');117118assert.deepStrictEqual(parseSSHConfigHostEntries(config), ['myserver']);119});120});121122suite('parseSSHGOutput', () => {123124test('parses standard ssh -G output', () => {125const output = [126'hostname 10.0.0.1',127'user admin',128'port 22',129'identityfile ~/.ssh/id_rsa',130'identityfile ~/.ssh/id_ed25519',131'forwardagent no',132].join('\n');133134assert.deepStrictEqual(parseSSHGOutput(output), {135hostname: '10.0.0.1',136user: 'admin',137port: 22,138identityFile: ['~/.ssh/id_rsa', '~/.ssh/id_ed25519'],139forwardAgent: false,140});141});142143test('parses forwardagent yes', () => {144const output = [145'hostname example.com',146'user root',147'port 22',148'forwardagent yes',149].join('\n');150151const result = parseSSHGOutput(output);152assert.strictEqual(result.forwardAgent, true);153});154155test('parses non-standard port', () => {156const output = [157'hostname example.com',158'user deploy',159'port 2222',160].join('\n');161162const result = parseSSHGOutput(output);163assert.strictEqual(result.port, 2222);164});165166test('handles missing user', () => {167const output = [168'hostname example.com',169'port 22',170].join('\n');171172const result = parseSSHGOutput(output);173assert.strictEqual(result.user, undefined);174});175176test('handles empty user', () => {177const output = [178'hostname example.com',179'user ',180'port 22',181].join('\n');182183const result = parseSSHGOutput(output);184assert.strictEqual(result.user, undefined);185});186187test('defaults port to 22 when missing', () => {188const output = 'hostname example.com\nuser root';189const result = parseSSHGOutput(output);190assert.strictEqual(result.port, 22);191});192193test('collects multiple identity files', () => {194const output = [195'hostname example.com',196'port 22',197'identityfile ~/.ssh/id_rsa',198'identityfile ~/.ssh/work_key',199'identityfile ~/.ssh/id_ed25519',200].join('\n');201202assert.deepStrictEqual(parseSSHGOutput(output).identityFile, [203'~/.ssh/id_rsa',204'~/.ssh/work_key',205'~/.ssh/id_ed25519',206]);207});208209test('handles empty output', () => {210assert.deepStrictEqual(parseSSHGOutput(''), {211hostname: '',212user: undefined,213port: 22,214identityFile: [],215forwardAgent: false,216});217});218219test('handles values with spaces', () => {220const output = 'hostname my host with spaces\nport 22';221const result = parseSSHGOutput(output);222assert.strictEqual(result.hostname, 'my host with spaces');223});224});225});226227228