Skip to content

Commit

Permalink
Replace SimpleXML with DOMDocument and use existing XML loader
Browse files Browse the repository at this point in the history
  • Loading branch information
mfn committed Sep 17, 2020
1 parent 92d5858 commit 9ea2b0e
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 47 deletions.
1 change: 0 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
"ext-json": "*",
"ext-libxml": "*",
"ext-mbstring": "*",
"ext-simplexml": "*",
"ext-xml": "*",
"ext-xmlwriter": "*",
"doctrine/instantiator": "^1.3.1",
Expand Down
91 changes: 45 additions & 46 deletions src/Runner/Filter/XmlTestsIterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@
*/
namespace PHPUnit\Runner\Filter;

use DOMElement;
use DOMXPath;
use Exception;
use LibXMLError;
use Generator;
use PHPUnit\Framework\TestCase;
use PHPUnit\Framework\TestSuite;
use PHPUnit\Runner\PhptTestCase;
use PHPUnit\Util\Xml\Loader as XmlLoader;
use RecursiveFilterIterator;
use RecursiveIterator;
use SimpleXMLElement;

/**
* @internal This class is not covered by the backward compatibility promise for PHPUnit
Expand Down Expand Up @@ -74,69 +76,66 @@ public function accept(): bool
*/
private function setFilter(string $xmlFile): void
{
$xml = $this->parseXmlFromFile($xmlFile);

// Regular PHPUnit tests
foreach ($xml->testCaseClass as $class) {
$className = $class['name']->__toString();
$xml = (new XmlLoader())->loadFile($xmlFile);
$xpath = new DOMXPath($xml);

foreach ($this->extractTestCases($xpath) as [$className, $methodName, $dataSet]) {
if (!isset($this->filter[$className])) {
$this->filter[$className] = [];
}

foreach ($class->children() as $method) {
$methodName = $method['name']->__toString();
if (!$dataSet) {
$this->filter[$className][$methodName] = true;

$dataSet = $method['dataSet'];
continue;
}

if (null === $dataSet) {
$this->filter[$className][$methodName] = true;
$name = "{$methodName} with data set {$dataSet}";
$this->filter[$className][$name] = true;
}

continue;
}
foreach ($this->extractPhptFile($xpath) as $path) {
$this->filter[PhptTestCase::class][$path] = true;
}
}

private function extractTestCases(DOMXPath $xpath): Generator
{
/** @var DOMElement $class */
foreach ($xpath->evaluate('/tests/testCaseClass') as $class) {
$className = $class->getAttribute('name');

$dataSet = $dataSet->__toString();
$name = "{$methodName} with data set {$dataSet}";
$this->filter[$className][$name] = true;
if (!$className) {
continue;
}
}

// Handle PHP tests
$this->filter[PhptTestCase::class] = [];
/** @var DOMElement $method */
foreach ($xpath->evaluate('testCaseMethod', $class) as $method) {
$methodName = $method->getAttribute('name');

if (!$methodName) {
continue;
}

$dataSet = $method->getAttribute('dataSet');

foreach ($xml->phptFile as $phptFile) {
$this->filter[PhptTestCase::class][$phptFile['path']->__toString()] = true;
yield [$className, $methodName, $dataSet];
}
}
}

/**
* @throws Exception
* @return Generator<string>
*/
private function parseXmlFromFile(string $xmlFile): SimpleXMLElement
private function extractPhptFile(DOMXPath $xpath): Generator
{
$oldValue = libxml_use_internal_errors(true);
$xml = simplexml_load_file($xmlFile);
libxml_use_internal_errors($oldValue);

if (false === $xml) {
$xmlError = libxml_get_last_error();
/* @var DOMElement $phptFile */
foreach ($xpath->evaluate('/tests/phptFile') as $phptFile) {
$path = $phptFile->getAttribute('path');

throw $this->xmlErrorToException($xmlError);
if ($path) {
yield $path;
}
}

return $xml;
}

private function xmlErrorToException(LibXMLError $xmlError): Exception
{
return new Exception(
sprintf(
'Error parsing XML tests: %s in %s:%d:%d',
trim($xmlError->message),
$xmlError->file,
$xmlError->line,
$xmlError->column
)
);
}
}

0 comments on commit 9ea2b0e

Please sign in to comment.