license import * as child_process from 'child_process' ; import * as net from 'net' ; import * as path from 'path' ; export function isTcpPortFree ( port ) { return new Promise ( ( resolve , reject ) => { const server = net . createServer ( ) ; server . on ( 'error' , ( e ) => { resolve ( false ) ; } ) ; server . on ( 'close' , ( ) => { resolve ( true ) ; } ) ; server . listen ( port , ( ) => { server . close ( ) ; } ) ; } ) ; } export function isTcpPortBound ( port ) { return new Promise ( ( resolve , reject ) => { const client = new net . Socket ( ) ; client . once ( 'connect' , ( ) => { resolve ( true ) ; } ) ; client . once ( 'error' , ( e ) => { resolve ( false ) ; } ) ; client . connect ( port ) ; } ) ; } export async function findFreeTcpPort ( ) { const range = { min : 32768 , max : 60000 } ; for ( let i = 0 ; i < 100 ; i ++ ) { let port = Math . floor ( Math . random ( ) * ( range . max - range . min ) + range . min ) ; if ( await isTcpPortFree ( port ) ) { return port ; } } throw new Error ( 'Unable to find a free port' ) ; } export interface OnPrepareConfig { workspace : string ; server : string ; } export function waitForServer ( port , timeout ) { return isTcpPortBound ( port ) . then ( isBound => { if ( ! isBound ) { if ( timeout <= 0 ) { throw new Error ( 'Timeout waiting for server to start' ) ; } const wait = Math . min ( timeout , 500 ) ; return new Promise ( ( res , rej ) => setTimeout ( res , wait ) ) . then ( ( ) => waitForServer ( port , timeout - wait ) ) ; } return true ; } ) ; } export interface ServerSpec { port : number ; } /**
 * Runs the specified server binary from a given workspace and waits for the server
 * being ready. The server binary will be resolved from the Bazel runfiles. Note that
 * the server will be launched with a random free port in order to support test concurrency
 * with Bazel.
 */ export async function runServer ( workspace , serverTarget , portFlag , serverArgs , timeout = 5000 ) { const serverPath = require . resolve ( `${ workspace }/${ serverTarget }` ) ; const port = await findFreeTcpPort ( ) ; const serverProcess = child_process . spawn ( serverPath , serverArgs . concat ( [ portFlag , port . toString ( ) ] ) , { stdio : 'inherit' } ) ; serverProcess . on ( 'exit' , exitCode => { if ( exitCode !== 0 ) { throw new Error ( `Server exited with error code: ${ exitCode }` ) ; } } ) ; await waitForServer ( port , timeout ) ; return { port } ; }