Chris@0: getMock('Drupal\Core\Extension\ModuleHandlerInterface'); Chris@0: $cache_backend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface'); Chris@0: $language_manager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface'); Chris@0: $this->pluginManager = new MigrationPluginManager($module_handler, $cache_backend, $language_manager); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Tests building dependencies for multiple migrations. Chris@0: * Chris@0: * @dataProvider dependencyProvider Chris@0: */ Chris@0: public function testDependencyBuilding($migrations_data, $result_ids) { Chris@0: $migrations = []; Chris@0: foreach ($migrations_data as $migration_id => $migration_data) { Chris@0: $migrations[$migration_id] = new TestMigrationMock($migration_id, $migration_data['dependencies']); Chris@0: } Chris@0: Chris@0: $ordered_migrations = $this->pluginManager->buildDependencyMigration($migrations, []); Chris@0: Chris@0: // Verify results. Chris@0: $this->assertEquals($result_ids, array_keys($ordered_migrations)); Chris@0: foreach ($migrations_data as $migration_id => $migration_data) { Chris@0: $migration = $migrations[$migration_id]; Chris@0: Chris@0: $requirements = $migration_data['result_requirements']; Chris@0: if (empty($requirements)) { Chris@0: $this->assertEquals([], $migration->set); Chris@0: } Chris@0: else { Chris@0: $requirements = array_combine($requirements, $requirements); Chris@0: Chris@0: $this->assertEquals(1, count($migration->set)); Chris@0: list($set_prop, $set_requirements) = reset($migration->set); Chris@0: $this->assertEquals('requirements', $set_prop); Chris@0: $this->assertEquals($requirements, $set_requirements); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Provide dependency data for testing. Chris@0: */ Chris@0: public function dependencyProvider() { Chris@0: return [ Chris@0: // Just one migration, with no dependencies. Chris@0: [ Chris@0: [ Chris@0: 'm1' => [ Chris@0: 'dependencies' => [], Chris@0: 'result_requirements' => [], Chris@0: ], Chris@0: ], Chris@0: ['m1'], Chris@0: ], Chris@0: Chris@0: // Just one migration, with required dependencies. Chris@0: [ Chris@0: [ Chris@0: 'm1' => [ Chris@0: 'dependencies' => [ Chris@0: 'required' => ['required1', 'required2'], Chris@0: ], Chris@0: 'result_requirements' => ['required1', 'required2'], Chris@0: ], Chris@0: ], Chris@0: ['m1'], Chris@0: ], Chris@0: Chris@0: // Just one migration, with optional dependencies. Chris@0: [ Chris@0: [ Chris@0: 'm1' => [ Chris@0: 'dependencies' => [ Chris@0: 'optional' => ['optional1'], Chris@0: ], Chris@0: 'result_requirements' => [], Chris@0: ], Chris@0: ], Chris@0: ['m1'], Chris@0: ], Chris@0: Chris@0: // Multiple migrations. Chris@0: [ Chris@0: [ Chris@0: 'm1' => [ Chris@0: 'dependencies' => [ Chris@0: 'required' => ['required1', 'required2'], Chris@0: ], Chris@0: 'result_requirements' => ['required1', 'required2'], Chris@0: ], Chris@0: 'm2' => [ Chris@0: 'dependencies' => [ Chris@0: 'optional' => ['optional1'], Chris@0: ], Chris@0: 'result_requirements' => [], Chris@0: ], Chris@0: ], Chris@0: ['m1', 'm2'], Chris@0: ], Chris@0: Chris@0: // Multiple migrations, reordered due to optional requirement. Chris@0: [ Chris@0: [ Chris@0: 'm1' => [ Chris@0: 'dependencies' => [ Chris@0: 'optional' => ['m2'], Chris@0: ], Chris@0: 'result_requirements' => [], Chris@0: ], Chris@0: 'm2' => [ Chris@0: 'dependencies' => [ Chris@0: 'optional' => ['optional1'], Chris@0: ], Chris@0: 'result_requirements' => [], Chris@0: ], Chris@0: ], Chris@0: ['m2', 'm1'], Chris@0: ], Chris@0: Chris@0: // Ensure that optional requirements aren't turned into required ones, Chris@0: // if the last migration has no optional deps. Chris@0: [ Chris@0: [ Chris@0: 'm1' => [ Chris@0: 'dependencies' => [ Chris@0: 'optional' => ['m2'], Chris@0: ], Chris@0: 'result_requirements' => [], Chris@0: ], Chris@0: 'm2' => [ Chris@0: 'dependencies' => [], Chris@0: 'result_requirements' => [], Chris@0: ], Chris@0: ], Chris@0: ['m2', 'm1'], Chris@0: ], Chris@0: ]; Chris@0: } Chris@0: Chris@0: } Chris@0: Chris@0: /** Chris@0: * A mock migration plugin. Chris@0: * Chris@0: * Why are we using a custom class here? Chris@0: * Chris@0: * 1. The function buildDependencyMigration() calls $migration->set(), which Chris@0: * is not actually in MigrationInterface. Chris@0: * Chris@0: * 2. The function buildDependencyMigration() calls array_multisort on an Chris@0: * array with mocks in it. PHPUnit mocks are really complex, and if PHP tries Chris@0: * to compare them it will die with "Nesting level too deep". Chris@0: */ Chris@0: class TestMigrationMock extends Migration { Chris@0: /** Chris@0: * The values passed into set(). Chris@0: * Chris@0: * @var array Chris@0: */ Chris@0: public $set = []; Chris@0: Chris@0: /** Chris@0: * TestMigrationMock constructor. Chris@0: */ Chris@0: public function __construct($id, $dependencies) { Chris@0: // Intentionally ignore parent constructor. Chris@0: $this->id = $id; Chris@0: $this->dependencies = $dependencies; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function id() { Chris@0: return $this->id; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getMigrationDependencies() { Chris@0: return $this->dependencies; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function set($prop, $value) { Chris@0: $this->set[] = func_get_args(); Chris@0: } Chris@0: Chris@0: }