executable = self::checkExecutable($executable); $this->url = sprintf('http://localhost:%d', $port); $this->args = $args; $this->environment = $environment ?: $_ENV; } /** * @return string */ public function getURL() { return $this->url; } /** * @return DriverService */ public function start() { if ($this->process !== null) { return $this; } $pipes = array(); $this->process = proc_open( sprintf("%s %s", $this->executable, implode(' ', $this->args)), $descriptorspec = array( 0 => array('pipe', 'r'), // stdin 1 => array('pipe', 'w'), // stdout 2 => array('pipe', 'a'), // stderr ), $pipes, null, $this->environment ); $checker = new URLChecker(); $checker->waitUntilAvailable(20 * 1000, $this->url.'/status'); return $this; } /** * @return DriverService */ public function stop() { if ($this->process === null) { return $this; } proc_terminate($this->process); $this->process = null; $checker = new URLChecker(); $checker->waitUntilUnAvailable(3 * 1000, $this->url.'/shutdown'); return $this; } /** * @return bool */ public function isRunning() { if ($this->process === null) { return false; } $status = proc_get_status($this->process); return $status['running']; } /** * Check if the executable is executable. * * @param string $executable * @return string * @throws Exception */ protected static function checkExecutable($executable) { if (!is_file($executable)) { throw new Exception("'$executable' is not a file."); } if (!is_executable($executable)) { throw new Exception("'$executable' is not executable."); } return $executable; } }