Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\Tests\Component\Serialization;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Component\Serialization\Exception\InvalidDataTypeException;
|
Chris@0
|
6 use Drupal\Component\Serialization\SerializationInterface;
|
Chris@0
|
7 use Drupal\Component\Serialization\Yaml;
|
Chris@0
|
8 use Drupal\Component\Serialization\YamlPecl;
|
Chris@0
|
9 use Drupal\Component\Serialization\YamlSymfony;
|
Chris@0
|
10 use PHPUnit\Framework\TestCase;
|
Chris@0
|
11
|
Chris@0
|
12 /**
|
Chris@0
|
13 * @coversDefaultClass \Drupal\Component\Serialization\Yaml
|
Chris@0
|
14 * @group Serialization
|
Chris@0
|
15 */
|
Chris@0
|
16 class YamlTest extends TestCase {
|
Chris@0
|
17
|
Chris@0
|
18 /**
|
Chris@0
|
19 * @var \PHPUnit_Framework_MockObject_MockObject
|
Chris@0
|
20 */
|
Chris@0
|
21 protected $mockParser;
|
Chris@0
|
22
|
Chris@0
|
23 public function setUp() {
|
Chris@0
|
24 parent::setUp();
|
Chris@0
|
25 $this->mockParser = $this->getMockBuilder('\stdClass')
|
Chris@0
|
26 ->setMethods(['encode', 'decode', 'getFileExtension'])
|
Chris@0
|
27 ->getMock();
|
Chris@0
|
28 YamlParserProxy::setMock($this->mockParser);
|
Chris@0
|
29 }
|
Chris@0
|
30
|
Chris@0
|
31 public function tearDown() {
|
Chris@0
|
32 YamlParserProxy::setMock(NULL);
|
Chris@0
|
33 parent::tearDown();
|
Chris@0
|
34 }
|
Chris@0
|
35
|
Chris@0
|
36 /**
|
Chris@0
|
37 * @covers ::decode
|
Chris@0
|
38 */
|
Chris@0
|
39 public function testDecode() {
|
Chris@0
|
40 $this->mockParser
|
Chris@0
|
41 ->expects($this->once())
|
Chris@0
|
42 ->method('decode');
|
Chris@0
|
43 YamlStub::decode('test');
|
Chris@0
|
44 }
|
Chris@0
|
45
|
Chris@0
|
46 /**
|
Chris@0
|
47 * @covers ::getFileExtension
|
Chris@0
|
48 */
|
Chris@0
|
49 public function testGetFileExtension() {
|
Chris@0
|
50 $this->mockParser
|
Chris@0
|
51 ->expects($this->never())
|
Chris@0
|
52 ->method('getFileExtension');
|
Chris@0
|
53 $this->assertEquals('yml', YamlStub::getFileExtension());
|
Chris@0
|
54 }
|
Chris@0
|
55
|
Chris@0
|
56 /**
|
Chris@0
|
57 * Tests all YAML files are decoded in the same way with Symfony and PECL.
|
Chris@0
|
58 *
|
Chris@0
|
59 * This test is a little bit slow but it tests that we do not have any bugs in
|
Chris@0
|
60 * our YAML that might not be decoded correctly in any of our implementations.
|
Chris@0
|
61 *
|
Chris@0
|
62 * @todo This should exist as an integration test not part of our unit tests.
|
Chris@0
|
63 * https://www.drupal.org/node/2597730
|
Chris@0
|
64 *
|
Chris@0
|
65 * @requires extension yaml
|
Chris@0
|
66 * @dataProvider providerYamlFilesInCore
|
Chris@0
|
67 */
|
Chris@0
|
68 public function testYamlFiles($file) {
|
Chris@0
|
69 $data = file_get_contents($file);
|
Chris@0
|
70 try {
|
Chris@0
|
71 $this->assertEquals(YamlSymfony::decode($data), YamlPecl::decode($data), $file);
|
Chris@0
|
72 }
|
Chris@0
|
73 catch (InvalidDataTypeException $e) {
|
Chris@0
|
74 // Provide file context to the failure so the exception message is useful.
|
Chris@0
|
75 $this->fail("Exception thrown parsing $file:\n" . $e->getMessage());
|
Chris@0
|
76 }
|
Chris@0
|
77 }
|
Chris@0
|
78
|
Chris@0
|
79 /**
|
Chris@14
|
80 * Ensures that decoding php objects does not work in PECL.
|
Chris@0
|
81 *
|
Chris@0
|
82 * @requires extension yaml
|
Chris@14
|
83 *
|
Chris@14
|
84 * @see \Drupal\Tests\Component\Serialization\YamlTest::testObjectSupportDisabledSymfony()
|
Chris@0
|
85 */
|
Chris@14
|
86 public function testObjectSupportDisabledPecl() {
|
Chris@0
|
87 $object = new \stdClass();
|
Chris@0
|
88 $object->foo = 'bar';
|
Chris@0
|
89 // In core all Yaml encoding is done via Symfony and it does not support
|
Chris@14
|
90 // objects so in order to encode an object we have to use the PECL
|
Chris@0
|
91 // extension.
|
Chris@0
|
92 // @see \Drupal\Component\Serialization\Yaml::encode()
|
Chris@0
|
93 $yaml = YamlPecl::encode([$object]);
|
Chris@0
|
94 $this->assertEquals(['O:8:"stdClass":1:{s:3:"foo";s:3:"bar";}'], YamlPecl::decode($yaml));
|
Chris@14
|
95 }
|
Chris@14
|
96
|
Chris@14
|
97 /**
|
Chris@14
|
98 * Ensures that decoding php objects does not work in Symfony.
|
Chris@14
|
99 *
|
Chris@14
|
100 * @requires extension yaml
|
Chris@14
|
101 *
|
Chris@14
|
102 * @see \Drupal\Tests\Component\Serialization\YamlTest::testObjectSupportDisabledPecl()
|
Chris@14
|
103 */
|
Chris@14
|
104 public function testObjectSupportDisabledSymfony() {
|
Chris@14
|
105 if (method_exists($this, 'setExpectedExceptionRegExp')) {
|
Chris@14
|
106 $this->setExpectedExceptionRegExp(InvalidDataTypeException::class, '/^Object support when parsing a YAML file has been disabled/');
|
Chris@14
|
107 }
|
Chris@14
|
108 else {
|
Chris@14
|
109 $this->expectException(InvalidDataTypeException::class);
|
Chris@14
|
110 $this->expectExceptionMessageRegExp('/^Object support when parsing a YAML file has been disabled/');
|
Chris@14
|
111 }
|
Chris@14
|
112 $object = new \stdClass();
|
Chris@14
|
113 $object->foo = 'bar';
|
Chris@14
|
114 // In core all Yaml encoding is done via Symfony and it does not support
|
Chris@14
|
115 // objects so in order to encode an object we have to use the PECL
|
Chris@14
|
116 // extension.
|
Chris@14
|
117 // @see \Drupal\Component\Serialization\Yaml::encode()
|
Chris@14
|
118 $yaml = YamlPecl::encode([$object]);
|
Chris@14
|
119 YamlSymfony::decode($yaml);
|
Chris@0
|
120 }
|
Chris@0
|
121
|
Chris@0
|
122 /**
|
Chris@0
|
123 * Data provider that lists all YAML files in core.
|
Chris@0
|
124 */
|
Chris@0
|
125 public function providerYamlFilesInCore() {
|
Chris@0
|
126 $files = [];
|
Chris@0
|
127 $dirs = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(__DIR__ . '/../../../../../', \RecursiveDirectoryIterator::FOLLOW_SYMLINKS));
|
Chris@0
|
128 foreach ($dirs as $dir) {
|
Chris@0
|
129 $pathname = $dir->getPathname();
|
Chris@14
|
130 // Exclude core/node_modules.
|
Chris@14
|
131 if ($dir->getExtension() == 'yml' && strpos($pathname, '/../../../../../node_modules') === FALSE) {
|
Chris@0
|
132 if (strpos($dir->getRealPath(), 'invalid_file') !== FALSE) {
|
Chris@0
|
133 // There are some intentionally invalid files provided for testing
|
Chris@0
|
134 // library API behaviours, ignore them.
|
Chris@0
|
135 continue;
|
Chris@0
|
136 }
|
Chris@0
|
137 $files[] = [$dir->getRealPath()];
|
Chris@0
|
138 }
|
Chris@0
|
139 }
|
Chris@0
|
140 return $files;
|
Chris@0
|
141 }
|
Chris@0
|
142
|
Chris@0
|
143 }
|
Chris@0
|
144
|
Chris@0
|
145 class YamlStub extends Yaml {
|
Chris@0
|
146
|
Chris@0
|
147 public static function getSerializer() {
|
Chris@0
|
148 return '\Drupal\Tests\Component\Serialization\YamlParserProxy';
|
Chris@0
|
149 }
|
Chris@0
|
150
|
Chris@0
|
151 }
|
Chris@0
|
152
|
Chris@0
|
153 class YamlParserProxy implements SerializationInterface {
|
Chris@0
|
154
|
Chris@0
|
155 /**
|
Chris@0
|
156 * @var \Drupal\Component\Serialization\SerializationInterface
|
Chris@0
|
157 */
|
Chris@0
|
158 protected static $mock;
|
Chris@0
|
159
|
Chris@0
|
160 public static function setMock($mock) {
|
Chris@0
|
161 static::$mock = $mock;
|
Chris@0
|
162 }
|
Chris@0
|
163
|
Chris@0
|
164 public static function encode($data) {
|
Chris@0
|
165 return static::$mock->encode($data);
|
Chris@0
|
166 }
|
Chris@0
|
167
|
Chris@0
|
168 public static function decode($raw) {
|
Chris@0
|
169 return static::$mock->decode($raw);
|
Chris@0
|
170 }
|
Chris@0
|
171
|
Chris@0
|
172 public static function getFileExtension() {
|
Chris@0
|
173 return static::$mock->getFileExtension();
|
Chris@0
|
174 }
|
Chris@0
|
175
|
Chris@0
|
176 }
|