MigrateSqlSourceTestBase.php

Same filename in other branches
  1. 9 core/modules/migrate/tests/src/Kernel/MigrateSqlSourceTestBase.php
  2. 8.9.x core/modules/migrate/tests/src/Kernel/MigrateSqlSourceTestBase.php
  3. 11.x core/modules/migrate/tests/src/Kernel/MigrateSqlSourceTestBase.php

Namespace

Drupal\Tests\migrate\Kernel

File

core/modules/migrate/tests/src/Kernel/MigrateSqlSourceTestBase.php

View source
<?php

declare (strict_types=1);
namespace Drupal\Tests\migrate\Kernel;

use Drupal\Core\Cache\MemoryCounterBackendFactory;
use Drupal\sqlite\Driver\Database\sqlite\Connection;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;

/**
 * Base class for tests of Migrate source plugins that use a database.
 */
abstract class MigrateSqlSourceTestBase extends MigrateSourceTestBase {
    
    /**
     * {@inheritdoc}
     */
    public function register(ContainerBuilder $container) {
        parent::register($container);
        $container->register('cache_factory', MemoryCounterBackendFactory::class)
            ->addArgument(new Reference('datetime.time'));
    }
    
    /**
     * Builds an in-memory SQLite database from a set of source data.
     *
     * @param array $source_data
     *   The source data, keyed by table name. Each table is an array containing
     *   the rows in that table.
     *
     * @return \Drupal\sqlite\Driver\Database\sqlite\Connection
     *   The SQLite database connection.
     */
    protected function getDatabase(array $source_data) {
        // Create an in-memory SQLite database. Plugins can interact with it like
        // any other database, and it will cease to exist when the connection is
        // closed.
        $connection_options = [
            'database' => ':memory:',
        ];
        $pdo = Connection::open($connection_options);
        $connection = new Connection($pdo, $connection_options);
        // Create the tables and fill them with data.
        foreach ($source_data as $table => $rows) {
            // Use the biggest row to build the table schema.
            $counts = array_map('count', $rows);
            asort($counts);
            $pilot = $rows[array_key_last($counts)];
            $connection->schema()
                ->createTable($table, [
                // SQLite uses loose affinity typing, so it's OK for every field to
                // be a text field.
'fields' => array_map(function () {
                    return [
                        'type' => 'text',
                    ];
                }, $pilot),
            ]);
            $fields = array_keys($pilot);
            $insert = $connection->insert($table)
                ->fields($fields);
            array_walk($rows, [
                $insert,
                'values',
            ]);
            $insert->execute();
        }
        return $connection;
    }
    
    /**
     * Tests the source plugin against a particular data set.
     *
     * @param array $source_data
     *   The source data that the plugin will read. See getDatabase() for the
     *   expected format.
     * @param array $expected_data
     *   The result rows the plugin is expected to return.
     * @param int $expected_count
     *   (optional) How many rows the source plugin is expected to return.
     * @param array $configuration
     *   (optional) Configuration for the source plugin.
     * @param mixed $high_water
     *   (optional) The value of the high water field.
     * @param string|null $expected_cache_key
     *   (optional) The expected cache key.
     *
     * @dataProvider providerSource
     *
     * @requires extension pdo_sqlite
     */
    public function testSource(array $source_data, array $expected_data, $expected_count = NULL, array $configuration = [], $high_water = NULL, $expected_cache_key = NULL) : void {
        $plugin = $this->getPlugin($configuration);
        // Since we don't yet inject the database connection, we need to use a
        // reflection hack to set it in the plugin instance.
        $reflector = new \ReflectionObject($plugin);
        $property = $reflector->getProperty('database');
        $property->setValue($plugin, $this->getDatabase($source_data));
        
        /** @var MemoryCounterBackend $cache **/
        $cache = \Drupal::cache('migrate');
        if ($expected_cache_key) {
            // Verify the computed cache key.
            $property = $reflector->getProperty('cacheKey');
            $this->assertSame($expected_cache_key, $property->getValue($plugin));
            // Cache miss prior to calling ::count().
            $this->assertFalse($cache->get($expected_cache_key, 'cache'));
            $this->assertSame([], $cache->getCounter('set'));
            $count = $plugin->count();
            $this->assertSame($expected_count, $count);
            $this->assertSame([
                $expected_cache_key => 1,
            ], $cache->getCounter('set'));
            // Cache hit afterwards.
            $cache_item = $cache->get($expected_cache_key, 'cache');
            $this->assertNotSame(FALSE, $cache_item, 'This is not a cache hit.');
            $this->assertSame($expected_count, $cache_item->data);
        }
        else {
            $this->assertSame([], $cache->getCounter('set'));
            $plugin->count();
            $this->assertSame([], $cache->getCounter('set'));
        }
        parent::testSource($source_data, $expected_data, $expected_count, $configuration, $high_water);
    }

}

Classes

Title Deprecated Summary
MigrateSqlSourceTestBase Base class for tests of Migrate source plugins that use a database.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.