1
0
Fork 0
mirror of https://we.phorge.it/source/arcanist.git synced 2024-12-01 19:22:41 +01:00
phorge-arcanist/src/unit/engine/ArcanistConfigurationDrivenUnitTestEngine.php
Tim McJilton b199ca8086 [ARCUNIT] Set the ConfigurationManager of ConfigurationDrivenUnitTestEngines
Summary:
The Configuration Manager is supported by ArcanistUnitTestEngine but not support by the ArcanistConfigurationDrivenUnitTestEngine.

Added the configuration manager as one of the initially set properties of an ArcUnitTestEngine created by the ArcanistConfigurationDrivenTestEngine

Test Plan: Ran arc unit against a project without the change, verified the Configuration was none. Added this change and ran again and verified it was set

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley, #blessed_reviewers

Subscribers: Korvin

Differential Revision: https://secure.phabricator.com/D19465
2018-06-05 20:58:47 +00:00

220 lines
5.7 KiB
PHP

<?php
final class ArcanistConfigurationDrivenUnitTestEngine
extends ArcanistUnitTestEngine {
protected function supportsRunAllTests() {
$engines = $this->buildTestEngines();
foreach ($engines as $engine) {
if ($engine->supportsRunAllTests()) {
return true;
}
}
return false;
}
public function buildTestEngines() {
$working_copy = $this->getWorkingCopy();
$config_path = $working_copy->getProjectPath('.arcunit');
if (!Filesystem::pathExists($config_path)) {
throw new ArcanistUsageException(
pht(
"Unable to find '%s' file to configure test engines. Create an ".
"'%s' file in the root directory of the working copy.",
'.arcunit',
'.arcunit'));
}
$data = Filesystem::readFile($config_path);
$config = null;
try {
$config = phutil_json_decode($data);
} catch (PhutilJSONParserException $ex) {
throw new PhutilProxyException(
pht(
"Expected '%s' file to be a valid JSON file, but ".
"failed to decode '%s'.",
'.arcunit',
$config_path),
$ex);
}
$test_engines = $this->loadAvailableTestEngines();
try {
PhutilTypeSpec::checkMap(
$config,
array(
'engines' => 'map<string, map<string, wild>>',
));
} catch (PhutilTypeCheckException $ex) {
throw new PhutilProxyException(
pht("Error in parsing '%s' file.", $config_path),
$ex);
}
$built_test_engines = array();
$all_paths = $this->getPaths();
foreach ($config['engines'] as $name => $spec) {
$type = idx($spec, 'type');
if ($type !== null) {
if (empty($test_engines[$type])) {
throw new ArcanistUsageException(
pht(
"Test engine '%s' specifies invalid type '%s'. ".
"Available test engines are: %s.",
$name,
$type,
implode(', ', array_keys($test_engines))));
}
$test_engine = clone $test_engines[$type];
} else {
// We'll raise an error below about the invalid "type" key.
// TODO: Can we just do the type check first, and simplify this a bit?
$test_engine = null;
}
try {
PhutilTypeSpec::checkMap(
$spec,
array(
'type' => 'string',
'include' => 'optional regex | list<regex>',
'exclude' => 'optional regex | list<regex>',
));
} catch (PhutilTypeCheckException $ex) {
throw new PhutilProxyException(
pht(
"Error in parsing '%s' file, for test engine '%s'.",
'.arcunit',
$name),
$ex);
}
if ($all_paths) {
$include = (array)idx($spec, 'include', array());
$exclude = (array)idx($spec, 'exclude', array());
$paths = $this->matchPaths(
$all_paths,
$include,
$exclude);
$test_engine->setPaths($paths);
}
$built_test_engines[] = $test_engine;
}
return $built_test_engines;
}
public function run() {
$renderer = $this->renderer;
$this->setRenderer(null);
$paths = $this->getPaths();
// If we are running with `--everything` then `$paths` will be `null`.
if (!$paths) {
$paths = array();
}
$engines = $this->buildTestEngines();
$all_results = array();
$exceptions = array();
foreach ($engines as $engine) {
$engine
->setWorkingCopy($this->getWorkingCopy())
->setEnableCoverage($this->getEnableCoverage())
->setConfigurationManager($this->getConfigurationManager())
->setRenderer($renderer);
// TODO: At some point, maybe we should emit a warning here if an engine
// doesn't support `--everything`, to reduce surprise when `--everything`
// does not really mean `--everything`.
if ($engine->supportsRunAllTests()) {
$engine->setRunAllTests($this->getRunAllTests());
}
try {
// TODO: Type check the results.
$results = $engine->run();
$all_results[] = $results;
foreach ($results as $result) {
// If the proxied engine renders its own test results then there
// is no need to render them again here.
if (!$engine->shouldEchoTestResults()) {
echo $renderer->renderUnitResult($result);
}
}
} catch (ArcanistNoEffectException $ex) {
$exceptions[] = $ex;
}
}
if (!$all_results) {
// If all engines throw an `ArcanistNoEffectException`, then we should
// preserve this behavior.
throw new ArcanistNoEffectException(pht('No tests to run.'));
}
return array_mergev($all_results);
}
public function shouldEchoTestResults() {
return false;
}
private function loadAvailableTestEngines() {
return id(new PhutilClassMapQuery())
->setAncestorClass('ArcanistUnitTestEngine')
->setUniqueMethod('getEngineConfigurationName', true)
->execute();
}
/**
* TODO: This is copied from @{class:ArcanistConfigurationDrivenLintEngine}.
*/
private function matchPaths(array $paths, array $include, array $exclude) {
$match = array();
foreach ($paths as $path) {
$keep = false;
if (!$include) {
$keep = true;
} else {
foreach ($include as $rule) {
if (preg_match($rule, $path)) {
$keep = true;
break;
}
}
}
if (!$keep) {
continue;
}
if ($exclude) {
foreach ($exclude as $rule) {
if (preg_match($rule, $path)) {
continue 2;
}
}
}
$match[] = $path;
}
return $match;
}
}