Arquivos
hhvm/hphp/test/run
T
Paul Tarjan 6e391b3c51 add Facebook test suite
We've been sprinkling FB-specific stuff into other tests. I think having a dedicated suite will make it obvious where to put things. I looked at all the failing tests when running the open source build and moved them here. I also had to rejigger the flib include, since that didn't work in repo mode.
2013-05-20 13:52:28 -07:00

320 linhas
7.8 KiB
PHP
Arquivo Executável

#!/usr/bin/env php
<?php
/**
* Run the test suites in various configurations.
*/
function usage() {
global $argv;
return "usage: $argv[0] [-m jit|hhir|interp] [-r] <test/directories>";
}
function help() {
global $argv;
$ztestexample = 'test/zend/good/*/*z*.php'; // sep. for syntax highlighting
$help = <<<EOT
This is the hhvm test-suite runner. For more detailed documentation,
see hphp/test/README.md.
The test argument may be a path to a php test file, a directory name, or
one of a few pre-defined suite names that this script knows about.
If you work with hhvm a lot, you might consider a bash alias:
alias ht="path/to/fbcode/hphp/test/run"
Examples:
# Quick tests in JIT mode:
% $argv[0]
# Quick tests in HHIR mode:
% $argv[0] -m hhir
# Slow tests in interp mode:
% $argv[0] -m interp test/slow
# Slow closure tests in JIT mode:
% $argv[0] test/slow/closure
# Slow closure tests in JIT mode with RepoAuthoritative:
% $argv[0] -r test/slow/closure
# Slow array tests, in RepoAuthoritative:
% $argv[0] -r test/slow/array
# Zend tests with a "z" in their name:
% $argv[0] $ztestexample
EOT;
return usage().$help;
}
function error($message) {
echo "$message\n";
exit(1);
}
function hphp_home() {
return __DIR__.'/../..';
}
function idx($array, $key, $default = null) {
return isset($array[$key]) ? $array[$key] : $default;
}
function idx_file($array, $key, $default = null) {
$file = is_file(idx($array, $key)) ? realpath($array[$key]) : $default;
if (!is_file($file)) {
error("$file doesn't exist");
}
return $file;
}
function bin_root() {
return idx($_ENV, 'FBMAKE_BIN_ROOT',
is_dir(hphp_home().'/_bin') ?
hphp_home().'/_bin' : # fbmake
hphp_home() # github
);
}
function verify_hhbc() {
return idx($_ENV, 'VERIFY_HHBC', bin_root().'/verify.hhbc');
}
function get_options($argv) {
$parameters = array(
'r' => 'repo',
'm:' => 'mode:',
'' => 'server',
'h' => 'help',
'' => 'commands',
);
$options = array();
$files = array();
for ($i = 1; $i < count($argv); $i++) {
$arg = $argv[$i];
$found = false;
if ($arg && $arg[0] == '-') {
foreach ($parameters as $short => $long) {
if ($arg == '-'.str_replace(':', '', $short) ||
$arg == '--'.str_replace(':', '', $long)) {
if (substr($long, -1, 1) == ':') {
$value = $argv[++$i];
} else {
$value = true;
}
$options[str_replace(':', '', $long)] = $value;
$found = true;
break;
}
}
}
if (!$found && $arg) {
$files[] = $arg;
}
}
return array($options, $files);
}
/*
* We support some 'special' file names, that just know where the test
* suites are, to avoid typing 'hphp/test/foo'.
*/
function map_convenience_filename($file) {
if ($file == 'jit' || $file == 'hhir' || $file == 'interp') {
error(
"I'm really sorry to change this, but now the mode is ".
"passed with '-m $file', and repo mode is turned on with '-r'"
);
}
$mappage = array(
'quick' => 'hphp/test/quick',
'slow' => 'hphp/test/slow',
'zend' => 'hphp/test/zend/good',
'zend_bad' => 'hphp/test/zend/bad',
'facebook' => 'hphp/facebook/test',
);
$m = null;
if (!preg_match('/([^\/]*)(.*)/', $file, $m) ||
!isset($mappage[$m[1]])) {
error("Not valid file or directory: '$file'");
}
if (!isset($m[2])) $m[2] = '';
return hphp_home().'/'.$mappage[$m[1]].$m[2];
}
function find_tests($files) {
if (!$files) {
$files = array(hphp_home().'/hphp/test/quick');
}
foreach ($files as &$file) {
if (!stat($file)) {
$file = map_convenience_filename($file);
}
$file = preg_replace(',//+,', '/', realpath($file));
$file = preg_replace(',^'.getcwd().'/,', '', $file);
}
$files = implode(' ', $files);
$tests = explode("\n", shell_exec("find $files -name '*.php' -o -name '*.hhas'"));
if (!$tests) {
error(usage());
}
asort($tests);
return array_filter($tests);
}
function find_config($tests, $name) {
$dirs = array_map('dirname', $tests);
$configs = array_map(function($test) use ($name) {
return find_config_for_dir($test, $name);
}, $tests);
$configs = array_unique($configs);
if (!count($configs) == 1) {
error(
"These tests would use many different configs and we only support ".
"using one for all the tests. Need these configs: ".
implode(' ', $configs).""
);
}
$ret = array_values($configs);
return $ret[0];
}
function find_config_for_dir($dir, $name) {
while ($dir && stat($dir)) {
$config = "$dir/$name";
if (is_file($config)) {
return $config;
}
$dir = substr($dir, 0, strrpos($dir, '/'));
}
return $name;
}
function is_server($options) {
return idx($options, 'server');
}
function file_arg($options) {
if (is_server($options)) {
return '-m server -vServer.SourceRoot=%s -p %s';
} else {
return '--file %3\$s';
}
}
function mode_arg($options) {
$repo_args = "-vRepo.Local.Mode=-- -vRepo.Central.Path=".verify_hhbc();
$jit_args = "$repo_args -vEval.Jit=1 -vEval.JitEnableRenameFunction=1";
$mode = idx($options, 'mode');
switch ($mode) {
case '':
case 'jit':
return "$jit_args -vEval.JitUseIR=0 -vEval.HHIRDisableTx64=0";
case 'hhir':
return "$jit_args -vEval.JitUseIR=1 -vEval.HHIRDisableTx64=1";
case 'interp':
return "$repo_args -vEval.Jit=0";
default:
error("-m must be one of hhir | jit | interp. Got: '$mode'");
}
}
function command_arg($options, $tests) {
return array(
idx_file($_ENV, 'HHVM', bin_root().'/hphp/hhvm/hhvm'),
'--config',
find_config($tests, 'config.hdf'),
file_arg($options),
mode_arg($options),
'-vEval.EnableArgsInBacktraces=true',
);
}
function hphp_arg($options, $tests) {
return array(
idx_file($_ENV, 'HPHP', bin_root().'/hphp/hhvm/hphp'),
'--config',
find_config($tests, 'hphp_config.hdf'),
);
}
function verify_args($options) {
$args = array();
if (is_server($options)) {
$args[] = '--server --port 8080 --home .';
}
$args[] = "--hhvm";
$args[] = idx_file($_ENV, 'HHVM',bin_root().'/hphp/hhvm/hhvm');
if (isset($options['repo'])) {
$args[] = '--repo 1';
} else {
$args[] = '--repo 0';
}
return $args;
}
function run($cmd, $tests) {
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w"),
);
$process = proc_open($cmd, $descriptorspec, $pipes);
if (!is_resource($process)) {
error("Can't run $cmd");
}
fwrite($pipes[0], implode(' ', $tests));
fclose($pipes[0]);
while(!feof($pipes[1])) {
echo fgets($pipes[1], 1024);
}
fclose($pipes[1]);
return proc_close($process);
}
list($options, $files) = get_options($argv);
if (isset($options['help'])) {
error(help());
}
$tests = find_tests($files);
$verify = array(
hphp_home().'/hphp/test/verify',
'--command="'.implode(' ', command_arg($options, $tests)).'"',
implode(' ', verify_args($options)),
);
if (isset($options['repo'])) {
$verify[] = '--hphp="'.implode(' ', hphp_arg($options, $tests)).'"';
}
$return_value = run(implode(' ', $verify), $tests);
if ($return_value || isset($options['commands'])) {
$command = implode(' ', command_arg($options, $tests));
$filename = 'FILENAME';
$extra_help = ' change FILENAME to the test you want';
if (count($tests) == 1) {
$filename = current($tests);
$extra_help = '';
}
$command = str_replace('%3\\$s', $filename, $command);
if (isset($options['repo'])) {
$command .= " -vRepo.Authoritative=true ";
$command = str_replace(verify_hhbc(), "$filename.repo/hhvm.hhbc", $command);
$command = implode(' ', hphp_arg($options, $tests)).
" -thhbc -l0 -k1 -o $filename.repo $filename\n".
$command;
}
print "\nTo run these by hand$extra_help:\n".
"$command\n";
}
exit($return_value);