minitest/main.hack (72 lines of code) (raw):
namespace HH\__Private\MiniTest;
use type HH\__Private\MiniTest\HackTest;
use namespace HH\Lib\{C, Dict, Keyset, Str};
<<__EntryPoint>>
async function main(): Awaitable<void> {
if (!\HH\Facts\enabled()) {
\fwrite(\STDERR, "ext_facts is required\n");
exit(1);
}
if (\ini_get('hhvm.hsl_systemlib_enabled')) {
\fwrite(\STDERR, "HSL Systemlib must be disabled\n");
exit(1);
}
if (!\function_exists("HH\\Lib\\Vec\\map")) {
\fwrite(\STDERR, "Native autoloader must be configured; couldn't find HSL\n");
exit(1);
}
if (!\class_exists(HackTest::class)) {
\fprintf(
\STDERR,
"Native autoloader must be configured; couldn't find %s\n",
HackTest::class,
);
exit(1);
}
$test_classes = Dict\filter(
\HH\Facts\all_types(),
$path ==>
Str\starts_with($path, 'tests/') && Str\ends_with($path, 'Test.php'),
);
// Usage: minitest [FooTest] [tests/Foo.php]
$argv = Keyset\map(\HH\global_get('argv') as vec<_>, $val ==> (string)$val)
|> Keyset\drop($$, 1);
if (!C\is_empty($argv)) {
$test_classes = Dict\filter_with_key(
$test_classes,
($class, $path) ==> {
foreach ($argv as $arg) {
if (Str\contains($class, $arg)) {
return true;
}
if (Str\starts_with($path, $arg)) {
return true;
}
}
return false;
},
);
}
if (C\is_empty($test_classes)) {
\fwrite(\STDERR, "No tests selected.\n");
exit(1);
}
foreach ($test_classes as $class => $_path) {
$rc = new \ReflectionClass($class);
if (!$rc->isInstantiable()) {
continue;
}
if (!$rc->isSubclassOf(HackTest::class)) {
continue;
}
$c = $rc->getConstructor();
if ($c !== null && $c->getNumberOfRequiredParameters() !== 0) {
\printf(
"!!! class %s has constructor with required parameters\n",
$class,
);
}
\printf("Starting %s...\n", $class);
$obj = $rc->newInstance() as HackTest;
await $obj->runAsync();
}
}