[BUGFIX] Side effects from LocalConfiguration in acceptance tests
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Tests / Testbase.php
index 199c478..f351bc1 100644 (file)
@@ -14,12 +14,14 @@ namespace TYPO3\CMS\Core\Tests;
  * The TYPO3 project - inspiring people to share!
  */
 
+use Doctrine\DBAL\DBALException;
+use Doctrine\DBAL\DriverManager;
 use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Database\ConnectionPool;
+use TYPO3\CMS\Core\Database\Schema\SchemaMigrator;
+use TYPO3\CMS\Core\Database\Schema\SqlReader;
 use TYPO3\CMS\Core\Utility\ArrayUtility;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Extbase\Object\ObjectManager;
-use TYPO3\CMS\Install\Service\SqlExpectedSchemaService;
-use TYPO3\CMS\Install\Service\SqlSchemaMigrationService;
 
 /**
  * This is a helper class used by unit, functional and acceptance test
@@ -220,10 +222,10 @@ class Testbase
      */
     public function setUpInstanceCoreLinks($instancePath)
     {
-        $linksToSet = array(
+        $linksToSet = [
             ORIGINAL_ROOT . 'typo3' => $instancePath . '/typo3',
             ORIGINAL_ROOT . 'index.php' => $instancePath . '/index.php'
-        );
+        ];
         foreach ($linksToSet as $from => $to) {
             $success = symlink($from, $to);
             if (!$success) {
@@ -282,7 +284,7 @@ class Testbase
             if (!file_exists($sourcePath)) {
                 throw new Exception(
                     'Path ' . $sourcePath . ' not found',
-                    1376745645
+                    1476109221
                 );
             }
             $destinationPath = $instancePath . '/' . ltrim($destinationPathToLinkInTestInstance, '/');
@@ -353,7 +355,7 @@ class Testbase
                 1397406356
             );
         }
-        return $originalConfigurationArray;
+        return $originalConfigurationArray['DB'];
     }
 
     /**
@@ -427,31 +429,31 @@ class Testbase
         array $additionalCoreExtensionsToLoad,
         array $testExtensionPaths
     ) {
-        $packageStates = array(
-            'packages' => array(),
+        $packageStates = [
+            'packages' => [],
             'version' => 5,
-        );
+        ];
 
         // Register default list of extensions and set active
         foreach ($defaultCoreExtensionsToLoad as $extensionName) {
-            $packageStates['packages'][$extensionName] = array(
+            $packageStates['packages'][$extensionName] = [
                 'packagePath' => 'typo3/sysext/' . $extensionName . '/'
-            );
+            ];
         }
 
         // Register additional core extensions and set active
         foreach ($additionalCoreExtensionsToLoad as $extensionName) {
-            $packageStates['packages'][$extensionName] = array(
+            $packageStates['packages'][$extensionName] = [
                 'packagePath' => 'typo3/sysext/' . $extensionName . '/'
-            );
+            ];
         }
 
         // Activate test extensions that have been symlinked before
         foreach ($testExtensionPaths as $extensionPath) {
             $extensionName = basename($extensionPath);
-            $packageStates['packages'][$extensionName] = array(
+            $packageStates['packages'][$extensionName] = [
                 'packagePath' => 'typo3conf/ext/' . $extensionName . '/'
-            );
+            ];
         }
 
         $result = $this->writeFile(
@@ -470,8 +472,8 @@ class Testbase
     }
 
     /**
-     * Populate $GLOBALS['TYPO3_DB'] and create test database
-     * For functional and acceptance tests
+     * Create a low level connection to dbms, without selecting the target database.
+     * Drop existing database if it exists and create a new one.
      *
      * @param string $databaseName Database name of this test instance
      * @param string $originalDatabaseName Original database name before suffix was added
@@ -481,33 +483,30 @@ class Testbase
     public function setUpTestDatabase($databaseName, $originalDatabaseName)
     {
         Bootstrap::getInstance()->initializeTypo3DbGlobal();
-        /** @var \TYPO3\CMS\Core\Database\DatabaseConnection $database */
-        $database = $GLOBALS['TYPO3_DB'];
-        if (!$database->sql_pconnect()) {
-            throw new Exception(
-                'TYPO3 Fatal Error: The current username, password or host was not accepted when the'
-                . ' connection to the database was attempted to be established!',
-                1377620117
-            );
+
+        // Drop database if exists. Directly using the Doctrine DriverManager to
+        // work around connection caching in ConnectionPool
+        $connectionParameters = $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default'];
+        unset($connectionParameters['dbname']);
+        $schemaManager = DriverManager::getConnection($connectionParameters)->getSchemaManager();
+
+        if (in_array($databaseName, $schemaManager->listDatabases(), true)) {
+            $schemaManager->dropDatabase($databaseName);
         }
 
-        // Drop database if exists
-        $database->admin_query('DROP DATABASE IF EXISTS `' . $databaseName . '`');
-        $createDatabaseResult = $database->admin_query('CREATE DATABASE `' . $databaseName . '` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci');
-        if (!$createDatabaseResult) {
+        try {
+            $schemaManager->createDatabase($databaseName);
+        } catch (DBALException $e) {
             $user = $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['user'];
             $host = $GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['host'];
             throw new Exception(
                 'Unable to create database with name ' . $databaseName . '. This is probably a permission problem.'
                 . ' For this instance this could be fixed executing:'
-                . ' GRANT ALL ON `' . $originalDatabaseName . '_%`.* TO `' . $user . '`@`' . $host . '`;',
+                . ' GRANT ALL ON `' . $originalDatabaseName . '_%`.* TO `' . $user . '`@`' . $host . '`;'
+                . ' Original message thrown by database layer: ' . $e->getMessage(),
                 1376579070
             );
         }
-        $database->setDatabaseName($databaseName);
-
-       // On windows, this still works, but throws a warning, which we need to discard.
-        @$database->sql_select_db();
     }
 
     /**
@@ -535,7 +534,7 @@ class Testbase
     }
 
     /**
-     * Populate $GLOBALS['TYPO3_DB'] and truncate all tables.
+     * Truncate all tables.
      * For functional and acceptance tests.
      *
      * @throws Exception
@@ -544,19 +543,13 @@ class Testbase
     public function initializeTestDatabaseAndTruncateTables()
     {
         Bootstrap::getInstance()->initializeTypo3DbGlobal();
-        /** @var \TYPO3\CMS\Core\Database\DatabaseConnection $database */
-        $database = $GLOBALS['TYPO3_DB'];
-        if (!$database->sql_pconnect()) {
-            throw new Exception(
-                'TYPO3 Fatal Error: The current username, password or host was not accepted when the'
-                . ' connection to the database was attempted to be established!',
-                1377620117
-            );
-        }
-        $database->setDatabaseName($GLOBALS['TYPO3_CONF_VARS']['DB']['Connections']['Default']['dbname']);
-        $database->sql_select_db();
-        foreach ($database->admin_get_tables() as $table) {
-            $database->admin_query('TRUNCATE ' . $table['Name'] . ';');
+
+        $connection = GeneralUtility::makeInstance(ConnectionPool::class)
+            ->getConnectionByName(ConnectionPool::DEFAULT_CONNECTION_NAME);
+        $schemaManager = $connection->getSchemaManager();
+
+        foreach ($schemaManager->listTables() as $table) {
+            $connection->truncate($table->getName());
         }
     }
 
@@ -579,36 +572,16 @@ class Testbase
      */
     public function createDatabaseStructure()
     {
-        /** @var SqlSchemaMigrationService $schemaMigrationService */
-        $schemaMigrationService = GeneralUtility::makeInstance(SqlSchemaMigrationService::class);
-        /** @var ObjectManager $objectManager */
-        $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
-        /** @var SqlExpectedSchemaService $expectedSchemaService */
-        $expectedSchemaService = $objectManager->get(SqlExpectedSchemaService::class);
-
-        // Raw concatenated ext_tables.sql and friends string
-        $expectedSchemaString = $expectedSchemaService->getTablesDefinitionString(true);
-        $statements = $schemaMigrationService->getStatementArray($expectedSchemaString, true);
-        list($_, $insertCount) = $schemaMigrationService->getCreateTables($statements, true);
-
-        $fieldDefinitionsFile = $schemaMigrationService->getFieldDefinitions_fileContent($expectedSchemaString);
-        $fieldDefinitionsDatabase = $schemaMigrationService->getFieldDefinitions_database();
-        $difference = $schemaMigrationService->getDatabaseExtra($fieldDefinitionsFile, $fieldDefinitionsDatabase);
-        $updateStatements = $schemaMigrationService->getUpdateSuggestions($difference);
-
-        $schemaMigrationService->performUpdateQueries($updateStatements['add'], $updateStatements['add']);
-        $schemaMigrationService->performUpdateQueries($updateStatements['change'], $updateStatements['change']);
-        $schemaMigrationService->performUpdateQueries($updateStatements['create_table'], $updateStatements['create_table']);
-
-        foreach ($insertCount as $table => $count) {
-            $insertStatements = $schemaMigrationService->getTableInsertStatements($statements, $table);
-            foreach ($insertStatements as $insertQuery) {
-                $insertQuery = rtrim($insertQuery, ';');
-                /** @var \TYPO3\CMS\Core\Database\DatabaseConnection $database */
-                $database = $GLOBALS['TYPO3_DB'];
-                $database->admin_query($insertQuery);
-            }
-        }
+        $schemaMigrationService = GeneralUtility::makeInstance(SchemaMigrator::class);
+        $sqlReader = GeneralUtility::makeInstance(SqlReader::class);
+        $sqlCode = $sqlReader->getTablesDefinitionString(true);
+
+        $createTableStatements = $sqlReader->getCreateTableStatementArray($sqlCode);
+
+        $schemaMigrationService->install($createTableStatements);
+
+        $insertStatements = $sqlReader->getInsertStatementArray($sqlCode);
+        $schemaMigrationService->importStaticData($insertStatements);
     }
 
     /**
@@ -627,19 +600,16 @@ class Testbase
             );
         }
 
-        /** @var \TYPO3\CMS\Core\Database\DatabaseConnection $database */
-        $database = $GLOBALS['TYPO3_DB'];
-
         $fileContent = file_get_contents($path);
         // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
         $previousValueOfEntityLoader = libxml_disable_entity_loader(true);
         $xml = simplexml_load_string($fileContent);
         libxml_disable_entity_loader($previousValueOfEntityLoader);
-        $foreignKeys = array();
+        $foreignKeys = [];
 
         /** @var $table \SimpleXMLElement */
         foreach ($xml->children() as $table) {
-            $insertArray = array();
+            $insertArray = [];
 
             /** @var $column \SimpleXMLElement */
             foreach ($table->children() as $column) {
@@ -659,16 +629,15 @@ class Testbase
             }
 
             $tableName = $table->getName();
-            $result = $database->exec_INSERTquery($tableName, $insertArray);
-            if ($result === false) {
-                throw new Exception(
-                    'Error when processing fixture file: ' . $path . ' Can not insert data to table ' . $tableName . ': ' . $database->sql_error(),
-                    1376746262
-                );
-            }
+            $connection = GeneralUtility::makeInstance(ConnectionPool::class)
+                ->getConnectionForTable($tableName);
+            $connection->insert(
+                $tableName,
+                $insertArray
+            );
             if (isset($table['id'])) {
                 $elementId = (string)$table['id'];
-                $foreignKeys[$tableName][$elementId] = $database->sql_insert_id();
+                $foreignKeys[$tableName][$elementId] = $connection->lastInsertId($tableName);
             }
         }
     }