migmag-1.0.x-dev/tests/src/Kernel/MigMagNativeMigrateSqlTestBase.php
tests/src/Kernel/MigMagNativeMigrateSqlTestBase.php
<?php namespace Drupal\Tests\migmag\Kernel; use Drupal\Core\Cache\MemoryCounterBackend; use Drupal\Core\Database\Database; use Drupal\Tests\migmag\Traits\MigMagMigrationTestDatabaseTrait; use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; use Drupal\migrate\Plugin\MigrateDestinationInterface; use Drupal\migrate\Plugin\MigrateSourceInterface; use Drupal\migrate\Row; /** * Base class for testing migrate source plugins with native databases. * * Most of the methods are copied from MigrateTestBase and are slightly * modified. * * @see \Drupal\Tests\migrate\Kernel\MigrateTestBase */ abstract class MigMagNativeMigrateSqlTestBase extends MigrateSqlSourceTestBase { use MigMagMigrationTestDatabaseTrait; /** * The source database connection. * * @var \Drupal\Core\Database\Connection */ protected $sourceDatabase; /** * {@inheritdoc} */ protected function setUp(): void { parent::setUp(); $destination_plugin = $this->prophesize(MigrateDestinationInterface::class); $destination_plugin->getPluginId()->willReturn($this->randomMachineName(16)); $this->migration->getDestinationPlugin()->willReturn( $destination_plugin->reveal() ); $this->createSourceMigrationConnection(); $this->sourceDatabase = Database::getConnection('default', 'migrate'); } /** * {@inheritdoc} * * @dataProvider providerSource */ public function testSource(array $source_data, array $expected_data, $expected_count = NULL, array $configuration = [], $high_water = NULL, $expected_cache_key = NULL): void { $this->importSourceDatabase($source_data); $plugin = $this->getPlugin($configuration); $clone_plugin = clone $plugin; // All source plugins must define IDs. $this->assertNotEmpty($plugin->getIds()); // If there is a high water mark, set it in the high water storage. if (isset($high_water)) { $this->container ->get('keyvalue') ->get('migrate:high_water') ->set($this->migration->reveal()->id(), $high_water); } // Tests the cacheability of the plugin. $cache = \Drupal::cache('migrate'); assert($cache instanceof MemoryCounterBackend); if (!is_callable([$cache, 'getCounter'])) { return; } if ($expected_cache_key) { // 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); // Verify the the computed cache key. $property = $reflector->getProperty('cacheKey'); $property->setAccessible(TRUE); $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')); } // Test source item counts. if (is_null($expected_count)) { $expected_count = count($expected_data); } // If an expected count was given, assert it only if the plugin is // countable. if (is_numeric($expected_count)) { $this->assertInstanceOf('\Countable', $plugin); $this->assertCount($expected_count, $plugin); } $i = 0; $actual_data = []; /** @var \Drupal\migrate\Row $row */ foreach ($plugin as $row) { $i++; $this->assertInstanceOf(Row::class, $row); $actual_data[] = $row->getSource(); } $this->assertEquals($expected_data, $actual_data); // False positives occur if the foreach is not entered. So, confirm the // foreach loop was entered if the expected count is greater than 0. if ($expected_count > 0) { $this->assertGreaterThan(0, $i); // Test that we can skip all rows. // The 'migrate_skip_all_rows_test' test module exists and installed only // in Drupal core 9.1+. if (\Drupal::moduleHandler()->moduleExists('migrate_skip_all_rows_test')) { \Drupal::state()->set('migrate_skip_all_rows_test_migrate_prepare_row', TRUE); $iterator_items = iterator_to_array($clone_plugin, FALSE); $this->assertEmpty($iterator_items, 'Row not skipped'); } } } /** * Tests the cacheability of the given source plugin. * * @param \Drupal\migrate\Plugin\MigrateSourceInterface $plugin * The source plugin instance. * @param int $expected_count * The expected source record count. * @param string|null $expected_cache_key * The expected cache key (if any). Defaults to NULL. */ protected function assertPluginCountCacheability(MigrateSourceInterface $plugin, int $expected_count, ?string $expected_cache_key) { /** @var \Drupal\Core\Cache\MemoryCounterBackend $cache * */ $cache = \Drupal::cache('migrate'); if (!is_callable([$cache, 'getCounter'])) { return; } if ($expected_cache_key) { // 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); // Verify the the computed cache key. $property = $reflector->getProperty('cacheKey'); $property->setAccessible(TRUE); $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')); } } /** * {@inheritdoc} * * @see \Drupal\Tests\migrate\Kernel\MigrateTestBase::cleanupMigrateConnection() */ protected function tearDown(): void { $this->cleanupSourceMigrateConnection(); parent::tearDown(); } }