public function invoke() { parent::invoke(); $future = new \ExecFuture("composer --no-ansi update"); $future->start(); try { do { list($out) = $future->read(); echo $out; } while (!$future->isReady()); } catch (\Exception $e) { list($err) = $future->read(); throw new \Exception($err); } }
/** * Runs the test suite. */ public function run() { $results = array(); $command = '(mkdir -p build && cd build && cmake ..)'; $command .= '&& make -C build all'; $command .= '&& make -C build test'; // Execute the test command & time it. $timeStart = microtime(true); $future = new ExecFuture($command); do { $future->read(); sleep(0.5); } while (!$future->isReady()); list($error, $stdout, $stderr) = $future->resolve(); $timeEnd = microtime(true); // Create a unit test result structure. $result = new ArcanistUnitTestResult(); $result->setNamespace('DerpVision'); $result->setName('Core'); $result->setDuration($timeEnd - $timeStart); if ($error == 0) { $result->setResult(ArcanistUnitTestResult::RESULT_PASS); } else { $result->setResult(ArcanistUnitTestResult::RESULT_FAIL); $result->setUserData($stdout . $stderr); } $results[] = $result; return $results; }
public function run() { $command = $this->getConfigurationManager()->getConfigFromAnySource('unit.engine.tap.command'); $future = new ExecFuture($command); do { list($stdout, $stderr) = $future->read(); echo $stdout; echo $stderr; sleep(0.5); } while (!$future->isReady()); list($error, $stdout, $stderr) = $future->resolve(); return $this->parseOutput($stdout); }
public function run() { $output = new TempFile(); $command = $this->getConfigurationManager()->getConfigFromAnySource('unit.engine.rspec.command'); if (!$command) { $command = 'rspec'; } $future = new ExecFuture($command . ' -f json -o ' . $output . ' -f Fuubar'); do { list($stdout, $stderr) = $future->read(); echo $stdout; sleep(0.5); } while (!$future->isReady()); return $this->parseOutput(Filesystem::readFile($output)); }
public function run() { if ($this->shouldRunSilently()) { echo "Running daemon '{$this->daemon}' silently. Use '--trace' or " . "'--verbose' to produce debugging output.\n"; } $root = phutil_get_library_root('phutil'); $root = dirname($root); $exec_dir = $root . '/scripts/daemon/exec/'; // NOTE: PHP implements proc_open() by running 'sh -c'. On most systems this // is bash, but on Ubuntu it's dash. When you proc_open() using bash, you // get one new process (the command you ran). When you proc_open() using // dash, you get two new processes: the command you ran and a parent // "dash -c" (or "sh -c") process. This means that the child process's PID // is actually the 'dash' PID, not the command's PID. To avoid this, use // 'exec' to replace the shell process with the real process; without this, // the child will call posix_getppid(), be given the pid of the 'sh -c' // process, and send it SIGUSR1 to keepalive which will terminate it // immediately. We also won't be able to do process group management because // the shell process won't properly posix_setsid() so the pgid of the child // won't be meaningful. // Format the exec command, which looks something like: // // exec ./exec_daemon DaemonName --trace -- --no-discovery $argv = array(); $argv[] = csprintf('exec ./exec_daemon.php %s', $this->daemon); foreach ($this->argv as $k => $arg) { $argv[] = csprintf('%s', $arg); } $argv[] = '--'; foreach ($this->moreArgs as $k => $arg) { $argv[] = csprintf('%s', $arg); } $command = implode(' ', $argv); while (true) { $this->logMessage('INIT', 'Starting process.'); $future = new ExecFuture('%C', $command); $future->setCWD($exec_dir); $future->setStdoutSizeLimit($this->captureBufferSize); $future->setStderrSizeLimit($this->captureBufferSize); $this->deadline = time() + $this->deadlineTimeout; $this->heartbeat = time() + self::HEARTBEAT_WAIT; $future->isReady(); $this->childPID = $future->getPID(); do { do { if ($this->traceMemory) { $memuse = number_format(memory_get_usage() / 1024, 1); $this->logMessage('RAMS', 'Overseer Memory Usage: ' . $memuse . ' KB'); } // We need a shortish timeout here so we can run the tick handler // frequently in order to process signals. $result = $future->resolve(1); list($stdout, $stderr) = $future->read(); $stdout = trim($stdout); $stderr = trim($stderr); if (strlen($stdout)) { $this->logMessage('STDO', $stdout); } if (strlen($stderr)) { $this->logMessage('STDE', $stderr); } $future->discardBuffers(); if ($result !== null) { list($err) = $result; if ($err) { $this->logMessage('FAIL', 'Process exited with error ' . $err . '.', $err); } else { $this->logMessage('DONE', 'Process exited successfully.'); } break 2; } if ($this->heartbeat < time()) { $this->heartbeat = time() + self::HEARTBEAT_WAIT; $this->dispatchEvent(self::EVENT_DID_HEARTBEAT); } } while (time() < $this->deadline); $this->logMessage('HANG', 'Hang detected. Restarting process.'); $this->annihilateProcessGroup(); } while (false); if ($this->inGracefulShutdown) { // If we just exited because of a graceful shutdown, break now. break; } $this->logMessage('WAIT', 'Waiting to restart process.'); sleep(self::RESTART_WAIT); if ($this->inGracefulShutdown) { // If we were awakend by a graceful shutdown, break now. break; } } // This is a clean exit after a graceful shutdown. $this->dispatchEvent(self::EVENT_WILL_EXIT); exit(0); }
public function testReadBuffering() { $str_len_8 = 'abcdefgh'; $str_len_4 = 'abcd'; // This is a write/read with no read buffer. $future = new ExecFuture('cat'); $future->write($str_len_8); do { $future->isReady(); list($read) = $future->read(); if (strlen($read)) { break; } } while (true); // We expect to get the entire string back in the read. $this->assertEqual($str_len_8, $read); $future->resolve(); // This is a write/read with a read buffer. $future = new ExecFuture('cat'); $future->write($str_len_8); // Set the read buffer size. $future->setReadBufferSize(4); do { $future->isReady(); list($read) = $future->read(); if (strlen($read)) { break; } } while (true); // We expect to get the entire string back in the read. $this->assertEqual($str_len_4, $read); $future->resolve(); }
public function run() { if ($this->shouldRunSilently()) { echo "Running daemon '{$this->daemon}' silently. Use '--trace' or " . "'--verbose' to produce debugging output.\n"; } $root = phutil_get_library_root('phutil'); $root = dirname($root); $exec_dir = $root . '/scripts/daemon/exec/'; // NOTE: PHP implements proc_open() by running 'sh -c'. On most systems this // is bash, but on Ubuntu it's dash. When you proc_open() using bash, you // get one new process (the command you ran). When you proc_open() using // dash, you get two new processes: the command you ran and a parent // "dash -c" (or "sh -c") process. This means that the child process's PID // is actually the 'dash' PID, not the command's PID. To avoid this, use // 'exec' to replace the shell process with the real process; without this, // the child will call posix_getppid(), be given the pid of the 'sh -c' // process, and send it SIGUSR1 to keepalive which will terminate it // immediately. We also won't be able to do process group management because // the shell process won't properly posix_setsid() so the pgid of the child // won't be meaningful. $exec_daemon = './exec_daemon.php'; $argv = $this->argv; array_unshift($argv, 'exec', $exec_daemon, $this->daemon); foreach ($argv as $k => $arg) { $argv[$k] = escapeshellarg($arg); } $command = implode(' ', $argv); while (true) { $this->logMessage('INIT', 'Starting process.'); $future = new ExecFuture($command); $future->setCWD($exec_dir); $future->setStdoutSizeLimit($this->captureBufferSize); $future->setStderrSizeLimit($this->captureBufferSize); $this->deadline = time() + $this->deadlineTimeout; $this->heartbeat = time() + self::HEARTBEAT_WAIT; $future->isReady(); $this->childPID = $future->getPID(); do { do { if ($this->traceMemory) { $memuse = number_format(memory_get_usage() / 1024, 1); $this->logMessage('RAMS', 'Overseer Memory Usage: ' . $memuse . ' KB'); } // We need a shortish timeout here so we can run the tick handler // frequently in order to process signals. $result = $future->resolve(1); list($stdout, $stderr) = $future->read(); $stdout = trim($stdout); $stderr = trim($stderr); if (strlen($stdout)) { $this->logMessage('STDO', $stdout, $stdout); } if (strlen($stderr)) { $this->logMessage('STDE', $stderr, $stderr); } $future->discardBuffers(); if ($result !== null) { list($err) = $result; if ($err) { $this->logMessage('FAIL', 'Process exited with error ' . $err . '.', $err); } else { $this->logMessage('DONE', 'Process exited successfully.'); } break 2; } if ($this->heartbeat < time()) { $this->heartbeat = time() + self::HEARTBEAT_WAIT; if ($this->conduitURI) { try { $this->conduit = new ConduitClient($this->conduitURI); $this->conduit->callMethodSynchronous('daemon.setstatus', array('daemonLogID' => $this->daemonLogID, 'status' => 'run')); } catch (Exception $ex) { } } } } while (time() < $this->deadline); $this->logMessage('HANG', 'Hang detected. Restarting process.'); $this->annihilateProcessGroup(); } while (false); $this->logMessage('WAIT', 'Waiting to restart process.'); sleep($this->restartDelay); } }
public function run() { $projectRoot = $this->getWorkingCopy()->getProjectRoot(); $cwd = getcwd(); $buildDir = $this->findBuildDirectory($projectRoot, $cwd); print "Using build directory '{$buildDir}'\n"; $makeVars = $this->getMakeVars($buildDir); $lit = $this->findLitExecutable($makeVars); print "Using lit executable '{$lit}'\n"; // We have to modify the format string, because llvm-lit does not like a '' argument $cmd = '%s ' . ($this->getEnableAsyncTests() ? '' : '-j1 ') . '%s 2>&1'; $litFuture = new ExecFuture($cmd, $lit, $buildDir . "/test"); $out = ""; $results = array(); $lastTime = microtime(true); $ready = false; $dots = ""; $numTests = 0; while (!$ready) { $ready = $litFuture->isReady(); $newout = $litFuture->readStdout(); if (strlen($newout) == 0) { usleep(100); continue; } $out .= $newout; if ($ready && strlen($out) > 0 && substr($out, -1) != "\n") { $out .= "\n"; } while (($nlPos = strpos($out, "\n")) !== FALSE) { $line = substr($out, 0, $nlPos + 1); $out = substr($out, $nlPos + 1); $res = ArcanistUnitTestResult::RESULT_UNSOUND; if (substr($line, 0, 6) == "PASS: "******"FAIL: ") { $res = ArcanistUnitTestResult::RESULT_FAIL; } elseif (substr($line, 0, 7) == "XPASS: "******"XFAIL: ") { $res = ArcanistUnitTestResult::RESULT_PASS; } elseif (substr($line, 0, 13) == "UNSUPPORTED: ") { $res = ArcanistUnitTestResult::RESULT_SKIP; } elseif (!$numTests && preg_match('/Testing: ([0-9]+) tests/', $line, $matches)) { $numTests = (int) $matches[1]; } if ($res == ArcanistUnitTestResult::RESULT_FAIL) { print "[1A"; } if ($res != ArcanistUnitTestResult::RESULT_SKIP && $res != ArcanistUnitTestResult::RESULT_PASS) { print "\r[K[1A" . $line . self::progress($results, $numTests); } if ($res == ArcanistUnitTestResult::RESULT_UNSOUND) { continue; } $result = new ArcanistUnitTestResult(); $result->setName(trim(substr($line, strpos($line, ':') + 1))); $result->setResult($res); $newTime = microtime(true); $result->setDuration($newTime - $lastTime); $lastTime = $newTime; $results[] = $result; $dots .= "."; print "\r[K[1A" . self::progress($results, $numTests); } } list($out1, $out2) = $litFuture->read(); print $out1; if ($out2) { throw new Exception('There was error output, even though it should have been redirected to stdout.'); } print "\n"; return $results; }
public function run() { $projectRoot = $this->getWorkingCopy()->getProjectRoot(); $cwd = getcwd(); $buildDir = $this->findBuildDirectory($projectRoot, $cwd); $polliObjDir = $buildDir; if (is_dir($buildDir . DIRECTORY_SEPARATOR . "tools" . DIRECTORY_SEPARATOR . "polly" . DIRECTORY_SEPARATOR . "tools" . DIRECTORY_SEPARATOR . "polli")) { $polliObjDir = $buildDir . DIRECTORY_SEPARATOR . "tools" . DIRECTORY_SEPARATOR . "polly" . DIRECTORY_SEPARATOR . "tools" . DIRECTORY_SEPARATOR . "polli"; } $polliTestDir = $polliObjDir . DIRECTORY_SEPARATOR . "test"; if (is_dir($buildDir . DIRECTORY_SEPARATOR . "bin") && file_exists($buildDir . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "llvm-lit")) { $lit = $buildDir . DIRECTORY_SEPARATOR . "bin" . DIRECTORY_SEPARATOR . "llvm-lit"; $cmd = "ninja -C " . $buildDir; print "Running ninja (" . $cmd . ")\n"; exec($cmd); } else { $makeVars = $this->getMakeVars($buildDir); $lit = $this->findLitExecutable($makeVars); } print "Using lit executable '{$lit}'\n"; // We have to modify the format string, because llvm-lit does not like a '' argument $cmd = '%s %s 2>&1'; $litFuture = new ExecFuture($cmd, $lit, $polliTestDir); $out = ""; $results = array(); $lastTime = microtime(true); $ready = false; $dots = ""; $numTests = 0; while (!$ready) { $ready = $litFuture->isReady(); $newout = $litFuture->readStdout(); if (strlen($newout) == 0) { usleep(100); continue; } $out .= $newout; if ($ready && strlen($out) > 0 && substr($out, -1) != "\n") { $out .= "\n"; } while (($nlPos = strpos($out, "\n")) !== FALSE) { $line = substr($out, 0, $nlPos + 1); $out = substr($out, $nlPos + 1); $res = ArcanistUnitTestResult::RESULT_UNSOUND; if (substr($line, 0, 6) == "PASS: "******"FAIL: ") { $res = ArcanistUnitTestResult::RESULT_FAIL; } elseif (substr($line, 0, 7) == "XPASS: "******"XFAIL: ") { $res = ArcanistUnitTestResult::RESULT_PASS; } elseif (substr($line, 0, 13) == "UNSUPPORTED: ") { $res = ArcanistUnitTestResult::RESULT_SKIP; } elseif (!$numTests && preg_match('/Testing: ([0-9]+) tests/', $line, $matches)) { $numTests = (int) $matches[1]; } if ($res == ArcanistUnitTestResult::RESULT_FAIL) { print "[0A"; } if ($res != ArcanistUnitTestResult::RESULT_SKIP && $res != ArcanistUnitTestResult::RESULT_PASS) { print "[K[0A" . $line . self::progress($results, $numTests); } if ($res == ArcanistUnitTestResult::RESULT_UNSOUND) { continue; } $result = new ArcanistUnitTestResult(); $result->setName(trim(substr($line, strpos($line, ':') + 1))); $result->setResult($res); $newTime = microtime(true); $result->setDuration($newTime - $lastTime); $lastTime = $newTime; $results[] = $result; $dots .= "."; print "\r[K[0A" . self::progress($results, $numTests); } } list($out1, $out2) = $litFuture->read(); print $out1; if ($out2) { throw new Exception('There was error output, even though it should have been redirected to stdout.'); } print "\n"; $timeThreshold = 0.05; $interestingTests = array(); foreach ($results as $result) { if ($result->getResult() != "pass") { $interestingTests[] = $result; } if ($result->getDuration() > $timeThreshold) { $interestingTests[] = $result; } } return $interestingTests; }
private function runPythonTestSuite($project_root, $testFilePath) { if (!is_dir($project_root . '/test_results')) { mkdir($project_root . '/test_results'); } // runs tests with code coverage for specified app names, // only giving results on files in pwd (to ignore 3rd party // code), verbosity 2 for individual test results, pipe stderr to // stdout as the test results are on stderr, adding additional args // specified by the .arcconfig $exec = $this->getPythonTestCommand($testFilePath); $future = new ExecFuture("%C", $exec); $future->setCWD($project_root); try { $future->resolvex(); $testExitCode = 0; } catch (CommandException $exc) { if ($exc->getError() > 1) { // 'nose' returns 1 when tests are failing/broken. throw $exc; } $testExitCode = $exc->getError(); } list($stdout, $stderr) = $future->read(); $stdout = trim($stdout); $stderr = trim($stderr); $testLines = explode("\n", $stdout); $testResults = array(); $testResults["testLines"] = $testLines; $testResults["testExitCode"] = $testExitCode; $xunit_path = $project_root . '/test_results/nosetests.xml'; $testResults["results"] = array(); $testResults["results"] = $this->parseXunitFile($xunit_path, $testResults["results"]); return $testResults; }