123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720 |
- <?php
- /**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
- namespace Magento\TestFramework;
- use Magento\Framework\Autoload\AutoloaderInterface;
- use Magento\Framework\App\Filesystem\DirectoryList;
- use Magento\Framework\App\DeploymentConfig;
- use Magento\Framework\Config\ConfigOptionsListConstants;
- use Magento\Framework\App\DeploymentConfig\Reader;
- use Magento\Framework\Filesystem\Glob;
- /**
- * Encapsulates application installation, initialization and uninstall.
- *
- * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
- * @SuppressWarnings(PHPMD.TooManyFields)
- */
- class Application
- {
- /**
- * Default application area.
- */
- const DEFAULT_APP_AREA = 'global';
- /**
- * DB vendor adapter instance.
- *
- * @var \Magento\TestFramework\Db\AbstractDb
- */
- protected $_db;
- /**
- * Shell command executor.
- *
- * @var \Magento\Framework\Shell
- */
- protected $_shell;
- /**
- * Configuration file that contains installation parameters.
- *
- * @var string
- */
- private $installConfigFile;
- /**
- * The loaded installation parameters.
- *
- * @var array
- */
- protected $installConfig;
- /**
- * Application *.xml configuration files.
- *
- * @var array
- */
- protected $_globalConfigDir;
- /**
- * Installation destination directory.
- *
- * @var string
- */
- protected $installDir;
- /**
- * Installation destination directory with configuration files.
- *
- * @var string
- */
- protected $_configDir;
- /**
- * Application initialization parameters.
- *
- * @var array
- */
- protected $_initParams = [];
- /**
- * Mode to run application.
- *
- * @var string
- */
- protected $_appMode;
- /**
- * Application area.
- *
- * @var null
- */
- protected $_appArea = null;
- /**
- * Primary DI Config.
- *
- * @var array
- */
- protected $_primaryConfigData = [];
- /**
- * Object manager factory.
- *
- * @var \Magento\TestFramework\ObjectManagerFactory
- */
- protected $_factory;
- /**
- * Directory list.
- *
- * @var \Magento\Framework\App\Filesystem\DirectoryList
- */
- protected $dirList;
- /**
- * Config file for integration tests.
- *
- * @var string
- */
- private $globalConfigFile;
- /**
- * Defines whether load test extension attributes or not.
- *
- * @var bool
- */
- private $loadTestExtensionAttributes;
- /**
- * @var bool
- */
- protected $dumpDb = true;
- /**
- * @var bool
- */
- protected $canLoadArea = true;
- /**
- * @var bool
- */
- protected $canInstallSequence = true;
- /**
- * Constructor.
- *
- * @param \Magento\Framework\Shell $shell
- * @param string $installDir
- * @param array $installConfigFile
- * @param string $globalConfigFile
- * @param string $globalConfigDir
- * @param string $appMode
- * @param AutoloaderInterface $autoloadWrapper
- * @param bool|null $loadTestExtensionAttributes
- */
- public function __construct(
- \Magento\Framework\Shell $shell,
- $installDir,
- $installConfigFile,
- $globalConfigFile,
- $globalConfigDir,
- $appMode,
- AutoloaderInterface $autoloadWrapper,
- $loadTestExtensionAttributes = false
- ) {
- if (getcwd() != BP . '/dev/tests/integration') {
- chdir(BP . '/dev/tests/integration');
- }
- $this->_shell = $shell;
- $this->installConfigFile = $installConfigFile;
- $this->_globalConfigDir = realpath($globalConfigDir);
- $this->_appMode = $appMode;
- $this->installDir = $installDir;
- $this->loadTestExtensionAttributes = $loadTestExtensionAttributes;
- $customDirs = $this->getCustomDirs();
- $this->dirList = new \Magento\Framework\App\Filesystem\DirectoryList(BP, $customDirs);
- \Magento\Framework\Autoload\Populator::populateMappings(
- $autoloadWrapper,
- $this->dirList
- );
- $this->_initParams = [
- \Magento\Framework\App\Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS => $customDirs,
- \Magento\Framework\App\State::PARAM_MODE => $appMode
- ];
- $driverPool = new \Magento\Framework\Filesystem\DriverPool;
- $configFilePool = new \Magento\Framework\Config\File\ConfigFilePool;
- $this->_factory = new \Magento\TestFramework\ObjectManagerFactory($this->dirList, $driverPool, $configFilePool);
- $this->_configDir = $this->dirList->getPath(DirectoryList::CONFIG);
- $this->globalConfigFile = $globalConfigFile;
- }
- /**
- * Retrieve the database adapter instance.
- *
- * @return \Magento\TestFramework\Db\AbstractDb
- */
- public function getDbInstance()
- {
- if (null === $this->_db) {
- if ($this->isInstalled()) {
- $configPool = new \Magento\Framework\Config\File\ConfigFilePool();
- $driverPool = new \Magento\Framework\Filesystem\DriverPool();
- $reader = new Reader($this->dirList, $driverPool, $configPool);
- $deploymentConfig = new DeploymentConfig($reader, []);
- $host = $deploymentConfig->get(
- ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT .
- '/' . ConfigOptionsListConstants::KEY_HOST
- );
- $user = $deploymentConfig->get(
- ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT .
- '/' . ConfigOptionsListConstants::KEY_USER
- );
- $password = $deploymentConfig->get(
- ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT .
- '/' . ConfigOptionsListConstants::KEY_PASSWORD
- );
- $dbName = $deploymentConfig->get(
- ConfigOptionsListConstants::CONFIG_PATH_DB_CONNECTION_DEFAULT .
- '/' . ConfigOptionsListConstants::KEY_NAME
- );
- } else {
- $installConfig = $this->getInstallConfig();
- $host = $installConfig['db-host'];
- $user = $installConfig['db-user'];
- $password = $installConfig['db-password'];
- $dbName = $installConfig['db-name'];
- }
- $this->_db = new Db\Mysql(
- $host,
- $user,
- $password,
- $dbName,
- $this->getTempDir(),
- $this->_shell
- );
- }
- return $this->_db;
- }
- /**
- * Gets installation parameters.
- *
- * @return array
- */
- protected function getInstallConfig()
- {
- if (null === $this->installConfig) {
- $this->installConfig = include $this->installConfigFile;
- }
- return $this->installConfig;
- }
- /**
- * Gets deployment configuration path.
- *
- * @return string
- */
- private function getLocalConfig()
- {
- return $this->_configDir . '/config.php';
- }
- /**
- * Get path to temporary directory.
- *
- * @return string
- */
- public function getTempDir()
- {
- return $this->installDir;
- }
- /**
- * Retrieve application initialization parameters.
- *
- * @return array
- */
- public function getInitParams()
- {
- return $this->_initParams;
- }
- /**
- * Weather the application is installed or not.
- *
- * @return bool
- */
- public function isInstalled()
- {
- return is_file($this->getLocalConfig());
- }
- /**
- * Create logger instance and rewrite already exist one in ObjectManager.
- *
- * @return \Psr\Log\LoggerInterface
- */
- private function initLogger()
- {
- $objectManager = Helper\Bootstrap::getObjectManager();
- /** @var \Psr\Log\LoggerInterface $logger */
- $logger = $objectManager->create(
- \Magento\TestFramework\ErrorLog\Logger::class,
- [
- 'name' => 'integration-tests',
- 'handlers' => [
- 'system' => $objectManager->create(
- \Magento\Framework\Logger\Handler\System::class,
- [
- 'exceptionHandler' => $objectManager->create(
- \Magento\Framework\Logger\Handler\Exception::class,
- ['filePath' => $this->installDir]
- ),
- 'filePath' => $this->installDir
- ]
- ),
- 'debug' => $objectManager->create(
- \Magento\Framework\Logger\Handler\Debug::class,
- ['filePath' => $this->installDir]
- ),
- ]
- ]
- );
- $objectManager->removeSharedInstance(\Magento\Framework\Logger\Monolog::class);
- $objectManager->addSharedInstance($logger, \Magento\Framework\Logger\Monolog::class);
- return $logger;
- }
- /**
- * Initialize application
- *
- * @param array $overriddenParams
- * @return void
- */
- public function initialize($overriddenParams = [])
- {
- $overriddenParams[\Magento\Framework\App\State::PARAM_MODE] = $this->_appMode;
- $overriddenParams = $this->_customizeParams($overriddenParams);
- $directories = isset($overriddenParams[\Magento\Framework\App\Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS])
- ? $overriddenParams[\Magento\Framework\App\Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS]
- : [];
- $directoryList = new DirectoryList(BP, $directories);
- /** @var \Magento\TestFramework\ObjectManager $objectManager */
- $objectManager = Helper\Bootstrap::getObjectManager();
- if (!$objectManager) {
- $objectManager = $this->_factory->create($overriddenParams);
- $objectManager->addSharedInstance($directoryList, \Magento\Framework\App\Filesystem\DirectoryList::class);
- $objectManager->addSharedInstance($directoryList, \Magento\Framework\Filesystem\DirectoryList::class);
- } else {
- $objectManager = $this->_factory->restore($objectManager, $directoryList, $overriddenParams);
- }
- /** @var \Magento\TestFramework\App\Filesystem $filesystem */
- $filesystem = $objectManager->get(\Magento\TestFramework\App\Filesystem::class);
- $objectManager->removeSharedInstance(\Magento\Framework\Filesystem::class);
- $objectManager->addSharedInstance($filesystem, \Magento\Framework\Filesystem::class);
- Helper\Bootstrap::setObjectManager($objectManager);
- $this->initLogger();
- $sequenceBuilder = $objectManager->get(\Magento\TestFramework\Db\Sequence\Builder::class);
- $objectManager->addSharedInstance($sequenceBuilder, \Magento\SalesSequence\Model\Builder::class);
- $objectManagerConfiguration = [
- 'preferences' => [
- \Magento\Framework\App\State::class => \Magento\TestFramework\App\State::class,
- \Magento\Framework\Mail\TransportInterface::class =>
- \Magento\TestFramework\Mail\TransportInterfaceMock::class,
- \Magento\Framework\Mail\Template\TransportBuilder::class
- => \Magento\TestFramework\Mail\Template\TransportBuilderMock::class,
- ]
- ];
- if ($this->loadTestExtensionAttributes) {
- $objectManagerConfiguration = array_merge(
- $objectManagerConfiguration,
- [
- \Magento\Framework\Api\ExtensionAttribute\Config\Reader::class => [
- 'arguments' => [
- 'fileResolver' => [
- 'instance' => \Magento\TestFramework\Api\Config\Reader\FileResolver::class
- ],
- ],
- ],
- ]
- );
- }
- $objectManager->configure($objectManagerConfiguration);
- /** Register event observer of Integration Framework */
- /** @var \Magento\Framework\Event\Config\Data $eventConfigData */
- $eventConfigData = $objectManager->get(\Magento\Framework\Event\Config\Data::class);
- $eventConfigData->merge(
- [
- 'core_app_init_current_store_after' => [
- 'integration_tests' => [
- 'instance' => \Magento\TestFramework\Event\Magento::class,
- 'name' => 'integration_tests'
- ]
- ]
- ]
- );
- if ($this->canLoadArea) {
- $this->loadArea(\Magento\TestFramework\Application::DEFAULT_APP_AREA);
- }
- \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->configure(
- $objectManager->get(\Magento\Framework\ObjectManager\DynamicConfigInterface::class)->getConfiguration()
- );
- \Magento\Framework\Phrase::setRenderer(
- $objectManager->get(\Magento\Framework\Phrase\Renderer\Placeholder::class)
- );
- if ($this->canInstallSequence) {
- /** @var \Magento\TestFramework\Db\Sequence $sequence */
- $sequence = $objectManager->get(\Magento\TestFramework\Db\Sequence::class);
- $sequence->generateSequences();
- }
- $objectManager->create(\Magento\TestFramework\Config::class, ['configPath' => $this->globalConfigFile])
- ->rewriteAdditionalConfig();
- }
- /**
- * Reset and initialize again an already installed application
- *
- * @param array $overriddenParams
- * @return void
- */
- public function reinitialize(array $overriddenParams = [])
- {
- $this->_resetApp();
- $this->initialize($overriddenParams);
- }
- /**
- * Run application normally, but with encapsulated initialization options
- *
- * @return void
- */
- public function run()
- {
- $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
- /** @var \Magento\Framework\App\Http $app */
- $app = $objectManager->get(\Magento\Framework\App\Http::class);
- $response = $app->launch();
- $response->sendResponse();
- }
- /**
- * Create install dir for integration framework
- *
- * @return void
- */
- public function createInstallDir()
- {
- $this->_ensureDirExists($this->installDir);
- $this->_ensureDirExists($this->_configDir);
- $this->copyAppConfigFiles();
- }
- /**
- * Cleanup both the database and the file system
- *
- * @return void
- */
- public function cleanup()
- {
- $this->createInstallDir();
- /**
- * @see \Magento\Setup\Mvc\Bootstrap\InitParamListener::BOOTSTRAP_PARAM
- */
- $this->_shell->execute(
- PHP_BINARY . ' -f %s setup:uninstall -vvv -n --magento-init-params=%s',
- [BP . '/bin/magento', $this->getInitParamsQuery()]
- );
- }
- /**
- * Install an application
- *
- * @param bool $cleanup
- * @return void
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- public function install($cleanup)
- {
- $dirs = \Magento\Framework\App\Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS;
- $this->_ensureDirExists($this->installDir);
- $this->_ensureDirExists($this->_configDir);
- $this->_ensureDirExists($this->_initParams[$dirs][DirectoryList::PUB][DirectoryList::PATH]);
- $this->_ensureDirExists($this->_initParams[$dirs][DirectoryList::MEDIA][DirectoryList::PATH]);
- $this->_ensureDirExists($this->_initParams[$dirs][DirectoryList::STATIC_VIEW][DirectoryList::PATH]);
- $this->_ensureDirExists($this->_initParams[$dirs][DirectoryList::VAR_DIR][DirectoryList::PATH]);
- $this->copyAppConfigFiles();
- $this->copyGlobalConfigFile();
- $installParams = $this->getInstallCliParams();
- // performance optimization: restore DB from last good dump to make installation on top of it (much faster)
- // do not restore from the database if the cleanup option is set to ensure we have a clean DB to test on
- $db = $this->getDbInstance();
- if ($db->isDbDumpExists() && !$cleanup) {
- $db->restoreFromDbDump();
- }
- // run install script
- $this->_shell->execute(
- PHP_BINARY . ' -f %s setup:install -vvv ' . implode(' ', array_keys($installParams)),
- array_merge([BP . '/bin/magento'], array_values($installParams))
- );
- // enable only specified list of caches
- $initParamsQuery = $this->getInitParamsQuery();
- $this->_shell->execute(
- PHP_BINARY . ' -f %s cache:disable -vvv --bootstrap=%s',
- [BP . '/bin/magento', $initParamsQuery]
- );
- $this->_shell->execute(
- PHP_BINARY . ' -f %s cache:enable -vvv %s %s %s %s --bootstrap=%s',
- [
- BP . '/bin/magento',
- \Magento\Framework\App\Cache\Type\Config::TYPE_IDENTIFIER,
- \Magento\Framework\App\Cache\Type\Layout::TYPE_IDENTIFIER,
- \Magento\Framework\App\Cache\Type\Translate::TYPE_IDENTIFIER,
- \Magento\Eav\Model\Cache\Type::TYPE_IDENTIFIER,
- $initParamsQuery,
- ]
- );
- // right after a clean installation, store DB dump for future reuse in tests or running the test suite again
- if (!$db->isDbDumpExists() && $this->dumpDb) {
- $this->getDbInstance()->storeDbDump();
- }
- }
- /**
- * Copies configuration files from the main code base, so the installation could proceed in the tests directory
- *
- * @return void
- */
- private function copyAppConfigFiles()
- {
- $globalConfigFiles = Glob::glob(
- $this->_globalConfigDir . '/{di.xml,*/di.xml,db_schema.xml,vendor_path.php}',
- Glob::GLOB_BRACE
- );
- foreach ($globalConfigFiles as $file) {
- $targetFile = $this->_configDir . str_replace($this->_globalConfigDir, '', $file);
- $this->_ensureDirExists(dirname($targetFile));
- if ($file !== $targetFile) {
- copy($file, $targetFile);
- }
- }
- }
-
- /**
- * Copies global configuration file from the tests folder (see TESTS_GLOBAL_CONFIG_FILE)
- *
- * @return void
- */
- private function copyGlobalConfigFile()
- {
- $targetFile = $this->_configDir . '/config.local.php';
- copy($this->globalConfigFile, $targetFile);
- }
- /**
- * Gets a list of CLI params for installation
- *
- * @return array
- */
- private function getInstallCliParams()
- {
- $params = $this->getInstallConfig();
- /**
- * Literal value is used instead of constant, because autoloader is not integrated with Magento Setup app
- * @see \Magento\Setup\Mvc\Bootstrap\InitParamListener::BOOTSTRAP_PARAM
- */
- $params['magento-init-params'] = $this->getInitParamsQuery();
- $result = [];
- foreach ($params as $key => $value) {
- if (!empty($value)) {
- $result["--{$key}=%s"] = $value;
- }
- }
- return $result;
- }
- /**
- * Encodes init params into a query string
- *
- * @return string
- */
- private function getInitParamsQuery()
- {
- return urldecode(http_build_query($this->_initParams));
- }
- /**
- * Sub-routine for merging custom parameters with the ones defined in object state
- *
- * @param array $params
- * @return array
- */
- public function _customizeParams($params)
- {
- return array_replace_recursive($this->_initParams, $params);
- }
- /**
- * Reset application global state
- */
- protected function _resetApp()
- {
- /** @var $objectManager \Magento\TestFramework\ObjectManager */
- $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
- $objectManager->clearCache();
- \Magento\Framework\Data\Form::setElementRenderer(null);
- \Magento\Framework\Data\Form::setFieldsetRenderer(null);
- \Magento\Framework\Data\Form::setFieldsetElementRenderer(null);
- $this->_appArea = null;
- }
- /**
- * Create a directory with write permissions or don't touch existing one
- *
- * @param string $dir
- * @return void
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- protected function _ensureDirExists($dir)
- {
- if (!file_exists($dir)) {
- $old = umask(0);
- mkdir($dir, 0777, true);
- umask($old);
- } elseif (!is_dir($dir)) {
- throw new \Magento\Framework\Exception\LocalizedException(__("'%1' is not a directory.", $dir));
- }
- }
- /**
- * Ge current application area
- *
- * @return string
- */
- public function getArea()
- {
- return $this->_appArea;
- }
- /**
- * Load application area
- *
- * @param string $areaCode
- * @return void
- * @throws \Magento\Framework\Exception\LocalizedException
- */
- public function loadArea($areaCode)
- {
- $this->_appArea = $areaCode;
- $scope = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
- \Magento\Framework\Config\Scope::class
- );
- $scope->setCurrentScope($areaCode);
- \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->configure(
- \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
- \Magento\Framework\App\ObjectManager\ConfigLoader::class
- )->load(
- $areaCode
- )
- );
- $app = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(\Magento\Framework\App\AreaList::class);
- $areasForPartialLoading = [
- \Magento\Framework\App\Area::AREA_GLOBAL,
- \Magento\Framework\App\Area::AREA_WEBAPI_REST,
- \Magento\Framework\App\Area::AREA_WEBAPI_SOAP,
- \Magento\Framework\App\Area::AREA_CRONTAB,
- \Magento\Framework\App\Area::AREA_GRAPHQL
- ];
- if (in_array($areaCode, $areasForPartialLoading, true)) {
- $app->getArea($areaCode)->load(\Magento\Framework\App\Area::PART_CONFIG);
- } else {
- \Magento\TestFramework\Helper\Bootstrap::getInstance()->loadArea($areaCode);
- }
- }
- /**
- * Gets customized directory paths
- *
- * @return array
- */
- protected function getCustomDirs()
- {
- $path = DirectoryList::PATH;
- $var = "{$this->installDir}/var";
- $generated = "{$this->installDir}/generated";
- $customDirs = [
- DirectoryList::CONFIG => [$path => "{$this->installDir}/etc"],
- DirectoryList::VAR_DIR => [$path => $var],
- DirectoryList::MEDIA => [$path => "{$this->installDir}/pub/media"],
- DirectoryList::STATIC_VIEW => [$path => "{$this->installDir}/pub/static"],
- DirectoryList::TMP_MATERIALIZATION_DIR => [$path => "{$var}/view_preprocessed/pub/static"],
- DirectoryList::GENERATED_CODE => [$path => "{$generated}/code"],
- DirectoryList::CACHE => [$path => "{$var}/cache"],
- DirectoryList::LOG => [$path => "{$var}/log"],
- DirectoryList::SESSION => [$path => "{$var}/session"],
- DirectoryList::TMP => [$path => "{$var}/tmp"],
- DirectoryList::UPLOAD => [$path => "{$var}/upload"],
- DirectoryList::PUB => [$path => "{$this->installDir}/pub"],
- ];
- return $customDirs;
- }
- }
|