![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/dev/tests/static/testsuite/Magento/Test/Integrity/Di/ |
<?php /** * Compiler test. Check compilation of DI definitions and code generation * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\Test\Integrity\Di; use Magento\Framework\Api\Code\Generator\Mapper; use Magento\Framework\Api\Code\Generator\SearchResults; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Component\ComponentRegistrar; use Magento\Framework\Interception\Code\InterfaceValidator; use Magento\Framework\ObjectManager\Code\Generator\Converter; use Magento\Framework\ObjectManager\Code\Generator\Factory; use Magento\Framework\ObjectManager\Code\Generator\Repository; use Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator; use Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator; use Magento\Framework\App\Utility\Files; use Magento\TestFramework\Integrity\PluginValidator; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CompilerTest extends \PHPUnit\Framework\TestCase { /** * @var string */ protected $_command; /** * @var \Magento\Framework\Shell */ protected $_shell; /** * @var string */ protected $_generationDir; /** * @var string */ protected $_compilationDir; /** * @var \Magento\Framework\ObjectManager\Config\Mapper\Dom() */ protected $_mapper; /** * @var \Magento\Framework\Code\Validator */ protected $_validator; /** * Class arguments reader * * @var PluginValidator */ protected $pluginValidator; /** * @var string[]|null */ private $pluginBlacklist; protected function setUp(): void { $this->_shell = new \Magento\Framework\Shell(new \Magento\Framework\Shell\CommandRenderer()); $basePath = BP; $basePath = str_replace('\\', '/', $basePath); $directoryList = new DirectoryList($basePath); $this->_generationDir = $directoryList->getPath(DirectoryList::GENERATED_CODE); $this->_compilationDir = $directoryList->getPath(DirectoryList::GENERATED_METADATA); $this->_command = 'php ' . $basePath . '/bin/magento setup:di:compile'; $booleanUtils = new \Magento\Framework\Stdlib\BooleanUtils(); $constInterpreter = new \Magento\Framework\Data\Argument\Interpreter\Constant(); $argumentInterpreter = new \Magento\Framework\Data\Argument\Interpreter\Composite( [ 'boolean' => new \Magento\Framework\Data\Argument\Interpreter\Boolean($booleanUtils), 'string' => new \Magento\Framework\Data\Argument\Interpreter\BaseStringUtils($booleanUtils), 'number' => new \Magento\Framework\Data\Argument\Interpreter\Number(), 'null' => new \Magento\Framework\Data\Argument\Interpreter\NullType(), 'object' => new \Magento\Framework\Data\Argument\Interpreter\DataObject($booleanUtils), 'const' => $constInterpreter, 'init_parameter' => new \Magento\Framework\App\Arguments\ArgumentInterpreter($constInterpreter), ], \Magento\Framework\ObjectManager\Config\Reader\Dom::TYPE_ATTRIBUTE ); // Add interpreters that reference the composite $argumentInterpreter->addInterpreter( 'array', new \Magento\Framework\Data\Argument\Interpreter\ArrayType($argumentInterpreter) ); $this->_mapper = new \Magento\Framework\ObjectManager\Config\Mapper\Dom( $argumentInterpreter, $booleanUtils, new \Magento\Framework\ObjectManager\Config\Mapper\ArgumentParser() ); $this->_validator = new \Magento\Framework\Code\Validator(); $this->_validator->add(new \Magento\Framework\Code\Validator\ConstructorIntegrity()); $this->_validator->add(new \Magento\Framework\Code\Validator\TypeDuplication()); $this->_validator->add(new \Magento\Framework\Code\Validator\ArgumentSequence()); $this->_validator->add(new \Magento\Framework\Code\Validator\ConstructorArgumentTypes()); $this->pluginValidator = new PluginValidator(new InterfaceValidator()); } /** * Return plugin blacklist class names * * @return string[] */ private function getPluginBlacklist(): array { if ($this->pluginBlacklist === null) { $blacklistFiles = str_replace( '\\', '/', realpath(__DIR__) . '/../_files/blacklist/compiler_plugins*.txt' ); $blacklistItems = []; foreach (glob($blacklistFiles) as $fileName) { $blacklistItems[] = file($fileName, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); } $blacklistItems = array_merge([], ...$blacklistItems); $this->pluginBlacklist = $blacklistItems; } return $this->pluginBlacklist; } /** * Validate DI config file * * @param string $file */ protected function _validateFile($file) { $dom = new \DOMDocument(); $dom->load($file); $data = $this->_mapper->convert($dom); foreach ($data as $instanceName => $parameters) { if (!isset($parameters['parameters']) || empty($parameters['parameters'])) { continue; } if (\Magento\Framework\App\Utility\Classes::isVirtual($instanceName)) { $instanceName = \Magento\Framework\App\Utility\Classes::resolveVirtualType($instanceName); } if (!$this->_classExistsAsReal($instanceName)) { continue; } $reflectionClass = new \ReflectionClass($instanceName); $constructor = $reflectionClass->getConstructor(); if (!$constructor) { $this->fail('Class ' . $instanceName . ' does not have __constructor'); } $parameters = $parameters['parameters']; $classParameters = $constructor->getParameters(); foreach ($classParameters as $classParameter) { $parameterName = $classParameter->getName(); if (array_key_exists($parameterName, $parameters)) { unset($parameters[$parameterName]); } } $message = 'Configuration of ' . $instanceName . ' contains data for non-existed parameters: ' . implode( ', ', array_keys($parameters) ); $this->assertEmpty($parameters, $message); } } /** * Checks if class is a real one or generated Factory * @param string $instanceName class name * @throws \PHPUnit\Framework\AssertionFailedError * @return bool */ protected function _classExistsAsReal($instanceName) { if (class_exists($instanceName)) { return true; } // check for generated factory if (substr($instanceName, -7) == 'Factory' && class_exists(substr($instanceName, 0, -7))) { return false; } $this->fail('Detected configuration of non existed class: ' . $instanceName); } /** * Get php classes list * * @return array */ protected function _phpClassesDataProvider() { $generationPath = str_replace('/', '\\', $this->_generationDir); $files = Files::init()->getPhpFiles(Files::INCLUDE_APP_CODE | Files::INCLUDE_LIBS); $patterns = ['/' . preg_quote($generationPath) . '/',]; $replacements = ['']; $componentRegistrar = new ComponentRegistrar(); foreach ($componentRegistrar->getPaths(ComponentRegistrar::MODULE) as $moduleName => $modulePath) { $patterns[] = '/' . preg_quote(str_replace('/', '\\', $modulePath)) . '/'; $replacements[] = '\\' . str_replace('_', '\\', $moduleName); } foreach ($componentRegistrar->getPaths(ComponentRegistrar::LIBRARY) as $libPath) { $patterns[] = '/' . preg_quote(str_replace('/', '\\', $libPath)) . '/'; $replacements[] = '\\Magento\\Framework'; } /** Convert file names into class name format */ $classes = []; foreach ($files as $file) { $file = str_replace('/', '\\', $file); $filePath = preg_replace($patterns, $replacements, $file); $className = substr($filePath, 0, -4); if (class_exists($className, false)) { $file = str_replace('\\', DIRECTORY_SEPARATOR, $file); $classes[$file] = $className; } } /** Build class inheritance hierarchy */ $output = []; $allowedFiles = array_keys($classes); foreach ($classes as $class) { if (!in_array($class, $output)) { $output[] = $this->_buildInheritanceHierarchyTree($class, $allowedFiles); } } $output = array_unique(array_merge([], ...$output)); /** Convert data into data provider format */ $outputClasses = []; foreach ($output as $className) { $outputClasses[] = [$className]; } return $outputClasses; } /** * Build inheritance hierarchy tree * * @param string $className * @param array $allowedFiles * @return array */ protected function _buildInheritanceHierarchyTree($className, array $allowedFiles) { $output = []; if (0 !== strpos($className, '\\')) { $className = '\\' . $className; } $class = new \ReflectionClass($className); $parent = $class->getParentClass(); $file = false; if ($parent) { $file = str_replace('\\', DIRECTORY_SEPARATOR, $parent->getFileName()); } /** Prevent analysis of non Magento classes */ if ($parent && in_array($file, $allowedFiles)) { $output = array_merge( $this->_buildInheritanceHierarchyTree($parent->getName(), $allowedFiles), [$className], $output ); } else { $output[] = $className; } return array_unique($output); } /** * Validate class * * @param string $className */ protected function _validateClass($className) { try { $this->_validator->validate($className); } catch (\Magento\Framework\Exception\ValidatorException $exceptions) { $this->fail($exceptions->getMessage()); } catch (\ReflectionException $exceptions) { $this->fail($exceptions->getMessage()); } } /** * Validate DI configuration */ public function testConfigurationOfInstanceParameters() { $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this); $invoker( function ($file) { $this->_validateFile($file); }, Files::init()->getDiConfigs(true) ); } /** * Validate constructor integrity */ public function testConstructorIntegrity() { $generatorIo = new \Magento\Framework\Code\Generator\Io( new \Magento\Framework\Filesystem\Driver\File(), $this->_generationDir ); $generator = new \Magento\Framework\Code\Generator( $generatorIo, [ Factory::ENTITY_TYPE => \Magento\Framework\ObjectManager\Code\Generator\Factory::class, Repository::ENTITY_TYPE => \Magento\Framework\ObjectManager\Code\Generator\Repository::class, Converter::ENTITY_TYPE => \Magento\Framework\ObjectManager\Code\Generator\Converter::class, Mapper::ENTITY_TYPE => \Magento\Framework\Api\Code\Generator\Mapper::class, SearchResults::ENTITY_TYPE => \Magento\Framework\Api\Code\Generator\SearchResults::class, ExtensionAttributesInterfaceGenerator::ENTITY_TYPE => \Magento\Framework\Api\Code\Generator\ExtensionAttributesInterfaceGenerator::class, ExtensionAttributesGenerator::ENTITY_TYPE => \Magento\Framework\Api\Code\Generator\ExtensionAttributesGenerator::class ] ); $generationAutoloader = new \Magento\Framework\Code\Generator\Autoloader($generator); spl_autoload_register([$generationAutoloader, 'load']); $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this); $invoker( function ($className) { $this->_validateClass($className); }, $this->_phpClassesDataProvider() ); spl_autoload_unregister([$generationAutoloader, 'load']); } /** * Test consistency of plugin interfaces */ public function testPluginInterfaces() { $invoker = new \Magento\Framework\App\Utility\AggregateInvoker($this); $invoker( function ($plugin, $type) { $this->validatePlugins($plugin, $type); }, $this->pluginDataProvider() ); } /** * Validate plugin interface * * @param string $plugin * @param string $type */ protected function validatePlugins($plugin, $type) { try { $module = \Magento\Framework\App\Utility\Classes::getClassModuleName($type); if (Files::init()->isModuleExists($module)) { $this->pluginValidator->validate($plugin, $type); } } catch (\Magento\Framework\Exception\ValidatorException $exception) { $this->fail($exception->getMessage()); } } /** * Get application plugins * * @return array * @throws \Exception */ protected function pluginDataProvider() { $files = Files::init()->getDiConfigs(); $plugins = []; foreach ($files as $file) { $dom = new \DOMDocument(); $dom->load($file); $xpath = new \DOMXPath($dom); $pluginList = $xpath->query('//config/type/plugin'); foreach ($pluginList as $node) { /** @var $node \DOMNode */ $type = $node->parentNode->attributes->getNamedItem('name')->nodeValue; $type = \Magento\Framework\App\Utility\Classes::resolveVirtualType($type); if ($node->attributes->getNamedItem('type')) { $plugin = $node->attributes->getNamedItem('type')->nodeValue; if (!in_array($plugin, $this->getPluginBlacklist())) { $plugin = \Magento\Framework\App\Utility\Classes::resolveVirtualType($plugin); $plugins[] = [$plugin, $type]; } } } } return $plugins; } }