GeneratorTest.php 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\Code;
  7. use Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceFactoryGenerator;
  8. use Magento\Framework\App\Filesystem\DirectoryList;
  9. use Magento\Framework\Filesystem;
  10. use Magento\Framework\Interception\Code\Generator as InterceptionGenerator;
  11. use Magento\Framework\ObjectManager\Code\Generator as DIGenerator;
  12. use Magento\TestFramework\Helper\Bootstrap;
  13. use PHPUnit\Framework\TestCase;
  14. require_once __DIR__ . '/GeneratorTest/SourceClassWithNamespace.php';
  15. require_once __DIR__ . '/GeneratorTest/ParentClassWithNamespace.php';
  16. require_once __DIR__ . '/GeneratorTest/SourceClassWithNamespaceExtension.php';
  17. /**
  18. * @magentoAppIsolation enabled
  19. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  20. */
  21. class GeneratorTest extends TestCase
  22. {
  23. const CLASS_NAME_WITH_NAMESPACE = GeneratorTest\SourceClassWithNamespace::class;
  24. /**
  25. * @var Generator
  26. */
  27. protected $_generator;
  28. /**
  29. * @var Generator/Io
  30. */
  31. protected $_ioObject;
  32. /**
  33. * @var Filesystem\Directory\Write
  34. */
  35. private $generatedDirectory;
  36. /**
  37. * @var Filesystem\Directory\Read
  38. */
  39. private $logDirectory;
  40. /**
  41. * @var string
  42. */
  43. private $testRelativePath = './Magento/Framework/Code/GeneratorTest/';
  44. /**
  45. * @inheritdoc
  46. */
  47. protected function setUp()
  48. {
  49. $objectManager = Bootstrap::getObjectManager();
  50. /** @var Filesystem $filesystem */
  51. $filesystem = $objectManager->get(Filesystem::class);
  52. $this->generatedDirectory = $filesystem->getDirectoryWrite(DirectoryList::GENERATED_CODE);
  53. $this->logDirectory = $filesystem->getDirectoryRead(DirectoryList::LOG);
  54. $generatedDirectoryAbsolutePath = $this->generatedDirectory->getAbsolutePath();
  55. $this->_ioObject = new Generator\Io(new Filesystem\Driver\File(), $generatedDirectoryAbsolutePath);
  56. $this->_generator = $objectManager->create(
  57. Generator::class,
  58. [
  59. 'ioObject' => $this->_ioObject,
  60. 'generatedEntities' => [
  61. ExtensionAttributesInterfaceFactoryGenerator::ENTITY_TYPE =>
  62. ExtensionAttributesInterfaceFactoryGenerator::class,
  63. DIGenerator\Factory::ENTITY_TYPE => DIGenerator\Factory::class,
  64. DIGenerator\Proxy::ENTITY_TYPE => DIGenerator\Proxy::class,
  65. InterceptionGenerator\Interceptor::ENTITY_TYPE => InterceptionGenerator\Interceptor::class,
  66. ]
  67. ]
  68. );
  69. $this->_generator->setObjectManager($objectManager);
  70. }
  71. /**
  72. * @inheritdoc
  73. */
  74. protected function tearDown()
  75. {
  76. $this->_generator = null;
  77. if ($this->generatedDirectory->isExist($this->testRelativePath)) {
  78. if (!$this->generatedDirectory->isWritable($this->testRelativePath)) {
  79. $this->generatedDirectory->changePermissionsRecursively($this->testRelativePath, 0775, 0664);
  80. }
  81. $this->generatedDirectory->delete($this->testRelativePath);
  82. }
  83. }
  84. protected function _clearDocBlock($classBody)
  85. {
  86. return preg_replace('/(\/\*[\w\W]*)\nclass/', 'class', $classBody);
  87. }
  88. /**
  89. * Generates a new file with Factory class and compares with the sample from the
  90. * SourceClassWithNamespaceFactory.php.sample file.
  91. */
  92. public function testGenerateClassFactoryWithNamespace()
  93. {
  94. $factoryClassName = self::CLASS_NAME_WITH_NAMESPACE . 'Factory';
  95. $this->assertEquals(Generator::GENERATION_SUCCESS, $this->_generator->generateClass($factoryClassName));
  96. $factory = Bootstrap::getObjectManager()->create($factoryClassName);
  97. $this->assertInstanceOf(self::CLASS_NAME_WITH_NAMESPACE, $factory->create());
  98. $content = $this->_clearDocBlock(
  99. file_get_contents($this->_ioObject->generateResultFileName($factoryClassName))
  100. );
  101. $expectedContent = $this->_clearDocBlock(
  102. file_get_contents(__DIR__ . '/_expected/SourceClassWithNamespaceFactory.php.sample')
  103. );
  104. $this->assertEquals($expectedContent, $content);
  105. }
  106. /**
  107. * Generates a new file with Proxy class and compares with the sample from the
  108. * SourceClassWithNamespaceProxy.php.sample file.
  109. */
  110. public function testGenerateClassProxyWithNamespace()
  111. {
  112. $proxyClassName = self::CLASS_NAME_WITH_NAMESPACE . '\Proxy';
  113. $this->assertEquals(Generator::GENERATION_SUCCESS, $this->_generator->generateClass($proxyClassName));
  114. $proxy = Bootstrap::getObjectManager()->create($proxyClassName);
  115. $this->assertInstanceOf(self::CLASS_NAME_WITH_NAMESPACE, $proxy);
  116. $content = $this->_clearDocBlock(
  117. file_get_contents($this->_ioObject->generateResultFileName($proxyClassName))
  118. );
  119. $expectedContent = $this->_clearDocBlock(
  120. file_get_contents(__DIR__ . '/_expected/SourceClassWithNamespaceProxy.php.sample')
  121. );
  122. $this->assertEquals($expectedContent, $content);
  123. }
  124. /**
  125. * Generates a new file with Interceptor class and compares with the sample from the
  126. * SourceClassWithNamespaceInterceptor.php.sample file.
  127. */
  128. public function testGenerateClassInterceptorWithNamespace()
  129. {
  130. $interceptorClassName = self::CLASS_NAME_WITH_NAMESPACE . '\Interceptor';
  131. $this->assertEquals(Generator::GENERATION_SUCCESS, $this->_generator->generateClass($interceptorClassName));
  132. $content = $this->_clearDocBlock(
  133. file_get_contents($this->_ioObject->generateResultFileName($interceptorClassName))
  134. );
  135. $expectedContent = $this->_clearDocBlock(
  136. file_get_contents(__DIR__ . '/_expected/SourceClassWithNamespaceInterceptor.php.sample')
  137. );
  138. $this->assertEquals($expectedContent, $content);
  139. }
  140. /**
  141. * Generates a new file with ExtensionInterfaceFactory class and compares with the sample from the
  142. * SourceClassWithNamespaceExtensionInterfaceFactory.php.sample file.
  143. */
  144. public function testGenerateClassExtensionAttributesInterfaceFactoryWithNamespace()
  145. {
  146. $factoryClassName = self::CLASS_NAME_WITH_NAMESPACE . 'ExtensionInterfaceFactory';
  147. $this->generatedDirectory->create($this->testRelativePath);
  148. $this->assertEquals(Generator::GENERATION_SUCCESS, $this->_generator->generateClass($factoryClassName));
  149. $factory = Bootstrap::getObjectManager()->create($factoryClassName);
  150. $this->assertInstanceOf(self::CLASS_NAME_WITH_NAMESPACE . 'Extension', $factory->create());
  151. $content = $this->_clearDocBlock(
  152. file_get_contents($this->_ioObject->generateResultFileName($factoryClassName))
  153. );
  154. $expectedContent = $this->_clearDocBlock(
  155. file_get_contents(__DIR__ . '/_expected/SourceClassWithNamespaceExtensionInterfaceFactory.php.sample')
  156. );
  157. $this->assertEquals($expectedContent, $content);
  158. }
  159. /**
  160. * It tries to generate a new class file when the generated directory is read-only
  161. */
  162. public function testGeneratorClassWithErrorSaveClassFile()
  163. {
  164. $factoryClassName = self::CLASS_NAME_WITH_NAMESPACE . 'Factory';
  165. $msgPart = 'Class ' . $factoryClassName . ' generation error: The requested class did not generate properly, '
  166. . 'because the \'generated\' directory permission is read-only.';
  167. $regexpMsgPart = preg_quote($msgPart);
  168. $this->expectException(\RuntimeException::class);
  169. $this->expectExceptionMessageRegExp("/.*$regexpMsgPart.*/");
  170. $this->generatedDirectory->create($this->testRelativePath);
  171. $this->generatedDirectory->changePermissionsRecursively($this->testRelativePath, 0555, 0444);
  172. $generatorResult = $this->_generator->generateClass($factoryClassName);
  173. $this->assertFalse($generatorResult);
  174. $pathToSystemLog = $this->logDirectory->getAbsolutePath('system.log');
  175. $this->assertContains($msgPart, file_get_contents($pathToSystemLog));
  176. }
  177. }