Test that stdin gets forwarded correctly
Co-Authored-By: Sergio Padrino <1083228+sergiou87@users.noreply.github.com>
This commit is contained in:
3
index.d.ts
vendored
3
index.d.ts
vendored
@@ -1,5 +1,8 @@
|
||||
export function getDesktopAskpassTrampolinePath(): string
|
||||
export function getDesktopAskpassTrampolineFilename(): string
|
||||
|
||||
export function getDesktopCredentialHelperTrampolinePath(): string
|
||||
export function getDesktopCredentialHelperTrampolineFilename(): string
|
||||
|
||||
export function getSSHWrapperPath(): string
|
||||
export function getSSHWrapperFilename(): string
|
||||
|
||||
17
index.js
17
index.js
@@ -15,6 +15,21 @@ function getDesktopAskpassTrampolineFilename() {
|
||||
: 'desktop-askpass-trampoline'
|
||||
}
|
||||
|
||||
function getDesktopCredentialHelperTrampolinePath() {
|
||||
return Path.join(
|
||||
__dirname,
|
||||
'build',
|
||||
'Release',
|
||||
getDesktopCredentialHelperTrampolineFilename()
|
||||
)
|
||||
}
|
||||
|
||||
function getDesktopCredentialHelperTrampolineFilename() {
|
||||
return process.platform === 'win32'
|
||||
? 'desktop-credential-helper-trampoline.exe'
|
||||
: 'desktop-credential-helper-trampoline'
|
||||
}
|
||||
|
||||
function getSSHWrapperPath() {
|
||||
return Path.join(__dirname, 'build', 'Release', getSSHWrapperFilename())
|
||||
}
|
||||
@@ -26,6 +41,8 @@ function getSSHWrapperFilename() {
|
||||
module.exports = {
|
||||
getDesktopAskpassTrampolinePath,
|
||||
getDesktopAskpassTrampolineFilename,
|
||||
getDesktopCredentialHelperTrampolinePath,
|
||||
getDesktopCredentialHelperTrampolineFilename,
|
||||
getSSHWrapperPath,
|
||||
getSSHWrapperFilename,
|
||||
}
|
||||
|
||||
@@ -2,46 +2,67 @@ const { stat, access } = require('fs').promises
|
||||
const { constants } = require('fs')
|
||||
const { execFile } = require('child_process')
|
||||
const { promisify } = require('util')
|
||||
const { getDesktopAskpassTrampolinePath } = require('../index')
|
||||
const { getDesktopAskpassTrampolinePath, getDesktopCredentialHelperTrampolinePath } = require('../index')
|
||||
const split2 = require('split2')
|
||||
const { createServer } = require('net')
|
||||
|
||||
const trampolinePath = getDesktopAskpassTrampolinePath()
|
||||
const askPassTrampolinePath = getDesktopAskpassTrampolinePath()
|
||||
const helperTrampolinePath = getDesktopCredentialHelperTrampolinePath()
|
||||
const run = promisify(execFile)
|
||||
|
||||
describe('desktop-trampoline', () => {
|
||||
it('exists and is a regular file', async () =>
|
||||
expect((await stat(trampolinePath)).isFile()).toBe(true))
|
||||
expect((await stat(askPassTrampolinePath)).isFile()).toBe(true))
|
||||
|
||||
it('can be executed by current process', () =>
|
||||
access(trampolinePath, constants.X_OK))
|
||||
access(askPassTrampolinePath, constants.X_OK))
|
||||
|
||||
it('fails when required environment variables are missing', () =>
|
||||
expect(run(trampolinePath, ['Username'])).rejects.toThrow())
|
||||
expect(run(askPassTrampolinePath, ['Username'])).rejects.toThrow())
|
||||
|
||||
it('forwards arguments and valid environment variables correctly', async () => {
|
||||
const captureSession = () => {
|
||||
const output = []
|
||||
let resolveOutput = null
|
||||
|
||||
const outputPromise = new Promise(resolve => {
|
||||
resolveOutput = resolve
|
||||
})
|
||||
|
||||
const server = createServer(socket => {
|
||||
let timeoutId = null
|
||||
socket.pipe(split2(/\0/)).on('data', data => {
|
||||
output.push(data.toString('utf8'))
|
||||
})
|
||||
|
||||
// Don't send anything and just close the socket after the trampoline is
|
||||
// done forwarding data.
|
||||
socket.end()
|
||||
// Hack: consider the session finished after 100ms of inactivity.
|
||||
// In a real-world scenario, you'd have to parse the data to know when
|
||||
// the session is finished.
|
||||
if (timeoutId !== null) {
|
||||
clearTimeout(timeoutId)
|
||||
timeoutId = null
|
||||
}
|
||||
timeoutId = setTimeout(() => {
|
||||
resolveOutput(output)
|
||||
socket.end()
|
||||
server.close()
|
||||
}, 100)
|
||||
})
|
||||
})
|
||||
server.unref()
|
||||
|
||||
const startTrampolineServer = async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
server.on('error', e => reject(e))
|
||||
server.listen(0, '127.0.0.1', () => {
|
||||
resolve(server.address().port)
|
||||
})
|
||||
const serverPortPromise = new Promise((resolve, reject) => {
|
||||
server.on('error', e => reject(e))
|
||||
server.listen(0, '127.0.0.1', () => {
|
||||
resolve(server.address().port)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return [serverPortPromise, outputPromise]
|
||||
}
|
||||
|
||||
it('forwards arguments and valid environment variables correctly', async () => {
|
||||
|
||||
const [portPromise, outputPromise] = captureSession()
|
||||
const port = await portPromise
|
||||
|
||||
const port = await startTrampolineServer()
|
||||
const env = {
|
||||
DESKTOP_TRAMPOLINE_TOKEN: '123456',
|
||||
DESKTOP_PORT: port,
|
||||
@@ -49,8 +70,9 @@ describe('desktop-trampoline', () => {
|
||||
}
|
||||
const opts = { env }
|
||||
|
||||
await run(trampolinePath, ['baz'], opts)
|
||||
await run(askPassTrampolinePath, ['baz'], opts)
|
||||
|
||||
const output = await outputPromise
|
||||
const outputArguments = output.slice(1, 2)
|
||||
expect(outputArguments).toStrictEqual(['baz'])
|
||||
// output[2] is the number of env variables
|
||||
@@ -58,7 +80,33 @@ describe('desktop-trampoline', () => {
|
||||
const outputEnv = output.slice(3, 3 + envc)
|
||||
expect(outputEnv).toHaveLength(1)
|
||||
expect(outputEnv).toContain('DESKTOP_TRAMPOLINE_TOKEN=123456')
|
||||
})
|
||||
|
||||
server.close()
|
||||
it('forwards stdin when running in credential-helper mode', async () => {
|
||||
|
||||
const [portPromise, outputPromise] = captureSession()
|
||||
const port = await portPromise
|
||||
|
||||
const cp = run(helperTrampolinePath, ['get'], { env: { DESKTOP_PORT: port } })
|
||||
cp.child.stdin.end('oh hai\n')
|
||||
|
||||
await cp
|
||||
|
||||
const output = await outputPromise
|
||||
expect(output.at(-1)).toBe('oh hai\n')
|
||||
})
|
||||
|
||||
it('doesn\'t forward stdin when running in askpass mode', async () => {
|
||||
|
||||
const [portPromise, outputPromise] = captureSession()
|
||||
const port = await portPromise
|
||||
|
||||
const cp = run(askPassTrampolinePath, ['get'], { env: { DESKTOP_PORT: port } })
|
||||
cp.child.stdin.end('oh hai\n')
|
||||
|
||||
await cp
|
||||
|
||||
const output = await outputPromise
|
||||
expect(output.at(-1)).toBe('')
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user