Skip to content

Commit

Permalink
Merge pull request doctrine#8 from Kern046/validate_xml_against_xsd
Browse files Browse the repository at this point in the history
Improve the XML Mapping Driver tests for XSD validation
  • Loading branch information
greg0ire committed Apr 14, 2022
2 parents 9cabfbf + bd31f3c commit ae4a3b1
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 57 deletions.
Expand Up @@ -1874,3 +1874,11 @@ public static function loadMetadata(ClassMetadataInfo $metadata): void
);
}
}

class UserIncorrectAttributes extends User
{
}

class UserMissingAttributes extends User
{
}
113 changes: 58 additions & 55 deletions tests/Doctrine/Tests/ORM/Mapping/XmlMappingDriverTest.php
Expand Up @@ -16,26 +16,18 @@
use Doctrine\Tests\Models\DDC3293\DDC3293User;
use Doctrine\Tests\Models\DDC3293\DDC3293UserPrefixed;
use Doctrine\Tests\Models\DDC889\DDC889Class;
use Doctrine\Tests\Models\DDC889\DDC889Entity;
use Doctrine\Tests\Models\DDC889\DDC889SuperClass;
use Doctrine\Tests\Models\Generic\SerializationModel;
use Doctrine\Tests\Models\GH7141\GH7141Article;
use Doctrine\Tests\Models\GH7316\GH7316Article;
use Doctrine\Tests\Models\ValueObjects\Name;
use Doctrine\Tests\Models\ValueObjects\Person;
use DOMDocument;
use Generator;
use Throwable;

use function array_filter;
use function array_map;
use function assert;
use function glob;
use function in_array;
use function is_array;
use function pathinfo;
use function sprintf;
use function substr_count;

use const DIRECTORY_SEPARATOR;
use const PATHINFO_FILENAME;

class XmlMappingDriverTest extends AbstractMappingDriverTest
{
Expand Down Expand Up @@ -167,77 +159,88 @@ public function testInvalidMappingFileException(): void
* @dataProvider dataValidSchema
* @group DDC-2429
*/
public function testValidateXmlSchema(string $xmlMappingFile): void
{
$xsdSchemaFile = __DIR__ . '/../../../../../doctrine-mapping.xsd';
$dom = new DOMDocument();

$dom->load($xmlMappingFile);

self::assertTrue($dom->schemaValidate($xsdSchemaFile));
public function testValidateXmlSchema(
string $class,
string $tableName,
array $fieldNames,
array $associationNames
): void {
$metadata = $this->createClassMetadata($class);

$this->assertInstanceOf(ClassMetadata::class, $metadata);
$this->assertEquals($metadata->getTableName(), $tableName);
$this->assertEquals($metadata->getFieldNames(), $fieldNames);
$this->assertEquals($metadata->getAssociationNames(), $associationNames);
}

/**
* @psalm-return list<array{string}>
* @psalm-return []array{0: class-string, 1: string, 2: list<string>, 3: list<string>}
*/
public static function dataValidSchema(): array
{
$list = glob(__DIR__ . '/xml/*.xml');
$invalid = [
'Doctrine.Tests.Models.DDC889.DDC889Class.dcm',
'Doctrine.Tests.ORM.Mapping.UserIncorrectAttributes.dcm',
'Doctrine.Tests.ORM.Mapping.UserMissingAttributes.dcm',
return [
[
User::class,
'cms_users',
['name', 'email', 'version', 'id'],
['address', 'phonenumbers', 'groups'],
],
[
DDC889Entity::class,
'DDC889Entity',
[],
[],
],
[
DDC889SuperClass::class,
'DDC889SuperClass',
['name'],
[],
],
];
assert(is_array($list));

$list = array_filter($list, static function (string $item) use ($invalid): bool {
return ! in_array(pathinfo($item, PATHINFO_FILENAME), $invalid, true);
});

return array_map(static function (string $item) {
return [$item];
}, $list);
}

/**
* @param array{0: class-string, 1: array<string, int>} $expectedExceptionOccurrences
*
* @dataProvider dataInvalidSchema
*/
public function testValidateIncorrectXmlSchema(string $xmlMappingFile, string $expectedExceptionMessage): void
public function testValidateIncorrectXmlSchema(string $class, array $expectedExceptionOccurrences): void
{
$xsdSchemaFile = __DIR__ . '/../../../../../doctrine-mapping.xsd';
$dom = new DOMDocument();

try {
$dom->load($xmlMappingFile);
$dom->schemaValidate($xsdSchemaFile);
} catch (Throwable $t) {
self::assertEquals($expectedExceptionMessage, $t->getMessage());
$this->createClassMetadata($class);
} catch (Throwable $throwable) {
$this->assertInstanceOf(MappingException::class, $throwable);

foreach ($expectedExceptionOccurrences as $exceptionContent => $occurrencesCount) {
$this->assertEquals($occurrencesCount, substr_count($throwable->getMessage(), $exceptionContent));
}
}
}

/**
* @psalm-return Generator<array<string, string>>
* @psalm-return []array{0: class-string, 1: array<string, int>}
*/
public static function dataInvalidSchema(): Generator
public static function dataInvalidSchema(): array
{
$invalidMappingsData = [
return [
[
'file' => 'Doctrine.Tests.Models.DDC889.DDC889Class.dcm',
'expected_exception' => 'DOMDocument::schemaValidate(): Element \'{http://doctrine-project.org/schemas/orm/doctrine-mapping}class\': This element is not expected.',
DDC889Class::class,
['This element is not expected' => 1],
],
[
'file' => 'Doctrine.Tests.ORM.Mapping.UserIncorrectAttributes.dcm',
'expected_exception' => 'DOMDocument::schemaValidate(): Element \'{http://doctrine-project.org/schemas/orm/doctrine-mapping}field\', attribute \'field\': The attribute \'field\' is not allowed.',
UserIncorrectAttributes::class,
[
'attribute \'field\': The attribute \'field\' is not allowed' => 2,
'The attribute \'name\' is required but missing' => 2,
'attribute \'fieldName\': The attribute \'fieldName\' is not allowed' => 1,
],
],
[
'file' => 'Doctrine.Tests.ORM.Mapping.UserMissingAttributes.dcm',
'expected_exception' => 'DOMDocument::schemaValidate(): Element \'{http://doctrine-project.org/schemas/orm/doctrine-mapping}field\': The attribute \'name\' is required but missing.',
UserMissingAttributes::class,
['The attribute \'name\' is required but missing' => 1],
],
];

foreach ($invalidMappingsData as $data) {
yield [sprintf(__DIR__ . '/xml/%s.xml', $data['file']), $data['expected_exception']];
}
}

/**
Expand Down
Expand Up @@ -5,7 +5,7 @@
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

<entity name="Doctrine\Tests\ORM\Mapping\User" table="cms_users">
<entity name="Doctrine\Tests\ORM\Mapping\UserIncorrectAttributes" table="cms_users">
<unique-constraints>
<unique-constraint columns="name,user_email" name="search_idx">
<options>
Expand Down
Expand Up @@ -5,7 +5,7 @@
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
https://www.doctrine-project.org/schemas/orm/doctrine-mapping.xsd">

<entity name="Doctrine\Tests\ORM\Mapping\User" table="cms_users">
<entity name="Doctrine\Tests\ORM\Mapping\UserMissingAttributes" table="cms_users">
<id name="id" type="integer" column="id">
<generator strategy="AUTO"/>
<sequence-generator sequence-name="tablename_seq" allocation-size="100" initial-value="1" />
Expand Down

0 comments on commit ae4a3b1

Please sign in to comment.