1 module.test ModuleUnitTest::testDependencyResolution()

Test dependency resolution.

File

core/modules/simpletest/tests/module.test, line 139
Tests for the module API.

Class

ModuleUnitTest
Unit tests for the module API.

Code

function testDependencyResolution() {
  // Enable the test module, disable the second module, and make sure that
  // other modules we are testing are not already enabled. (If they were, the
  // tests below would not work correctly.)
  module_enable(array('module_test'), FALSE);
  module_disable(array('dependency_test2'), FALSE);
  $this->assertTrue(module_exists('module_test'), 'Test module is enabled.');
  $this->assertFalse(module_exists('dependency_test3'), 'Third module is disabled.');
  $this->assertFalse(module_exists('dependency_test2'), 'Second module is disabled.');
  $this->assertFalse(module_exists('dependency_test1'), 'First module is disabled.');

  // First, create a fake missing dependency. Test3 depends on the test2
  // module, which depends on a made-up module, foo. Nothing should be
  // installed.
  state_set('dependency_test', 'missing dependency');
  backdrop_static_reset('system_rebuild_module_data');
  $result = module_enable(array('dependency_test3'));
  $this->assertFalse($result, 'module_enable() returns FALSE if dependencies are missing.');
  $this->assertFalse(module_exists('dependency_test3'), 'module_enable() aborts if dependencies are missing.');

  // Now, fix the missing dependency. Test3 module depends on test2, but test2
  // depends on test1 module. module_enable() should work.
  state_set('dependency_test', 'dependency');
  backdrop_static_reset('system_rebuild_module_data');
  $result = module_enable(array('dependency_test3'));
  $this->assertTrue($result, 'module_enable() returns the correct value.');
  // Verify that the fake dependency chain was installed.
  $this->assertTrue(module_exists('dependency_test2') && module_exists('dependency_test1'), 'Dependency chain was installed by module_enable().');
  // Verify that the original module was installed.
  $this->assertTrue(module_exists('dependency_test3'), 'Module installation with unlisted dependencies succeeded.');
  // Finally, verify that the modules were enabled in the correct order.
  $this->assertEqual(state_get('test_module_enable_order', array()), array('dependency_test1', 'dependency_test2', 'dependency_test3'), 'Modules were enabled in the correct order by module_enable().');

  // Now, disable the test1 module. Both test3 and test2 should be disabled
  // as well, in the correct order.
  module_disable(array('dependency_test1'));
  $this->assertTrue(!module_exists('dependency_test3') && !module_exists('dependency_test2'), 'Dependency chain was disabled by module_disable().');
  $this->assertFalse(module_exists('dependency_test1'), 'Disabling a module with unlisted dependents succeeded.');
  $this->assertEqual(state_get('test_module_disable_order', array()), array('dependency_test3', 'dependency_test2', 'dependency_test1'), 'Modules were disabled in the correct order by module_disable().');

  // Disable a module that is listed as a dependency by the installation
  // profile. Make sure that the profile itself is not on the list of
  // dependent modules to be disabled.
  $profile = backdrop_get_profile();
  $info = install_profile_info($profile);
  $this->assertTrue(in_array('comment', $info['dependencies']), 'Comment module is listed as a dependency of the installation profile.');
  $this->assertTrue(module_exists('comment'), 'Comment module is enabled.');
  module_disable(array('comment'));
  $this->assertFalse(module_exists('comment'), 'Comment module was disabled.');
  $disabled_modules = state_get('test_module_disable_order', array());
  $this->assertTrue(in_array('comment', $disabled_modules), 'Comment module is in the list of disabled modules.');
  $this->assertFalse(in_array($profile, $disabled_modules), 'The installation profile is not in the list of disabled modules.');

  // Try to uninstall the test1 module by itself. This should be rejected,
  // since the modules which it depends on need to be uninstalled first, and
  // that is too destructive to perform automatically.
  $result = backdrop_uninstall_modules(array('dependency_test1'));
  $this->assertFalse($result, 'Calling backdrop_uninstall_modules() on a module whose dependents are not uninstalled fails.');
  foreach (array('dependency_test3', 'dependency_test2', 'dependency_test1') as $module) {
    $this->assertNotEqual(backdrop_get_installed_schema_version($module), SCHEMA_UNINSTALLED, format_string('The @module module was not uninstalled.', array('@module' => $module)));
  }

  // Now uninstall all three modules explicitly, but in the incorrect order,
  // and make sure that backdrop_uninstall_modules() uninstalled them in the
  // correct sequence.
  $result = backdrop_uninstall_modules(array('dependency_test2', 'dependency_test1', 'dependency_test3'));
  $this->assertTrue($result, t('backdrop_uninstall_modules() returns the correct value.'));
  foreach (array('dependency_test3', 'dependency_test2', 'dependency_test1') as $module) {
    $this->assertEqual(backdrop_get_installed_schema_version($module), SCHEMA_UNINSTALLED, format_string('The @module module was uninstalled.', array('@module' => $module)));
  }
  $this->assertEqual(state_get('test_module_uninstall_order', array()), array('dependency_test3', 'dependency_test2', 'dependency_test1'), 'Modules were uninstalled in the correct order by backdrop_uninstall_modules().');

  // Uninstall the profile module from above, and make sure that the profile
  // itself is not on the list of dependent modules to be uninstalled.
  $result = backdrop_uninstall_modules(array('comment'));
  $this->assertTrue($result, 'backdrop_uninstall_modules() returns the correct value.');
  $this->assertEqual(backdrop_get_installed_schema_version('comment'), SCHEMA_UNINSTALLED, 'Comment module was uninstalled.');
  $uninstalled_modules = state_get('test_module_uninstall_order', array());
  $this->assertTrue(in_array('comment', $uninstalled_modules), 'Comment module is in the list of uninstalled modules.');
  $this->assertFalse(in_array($profile, $uninstalled_modules), 'The installation profile is not in the list of uninstalled modules.');

  // Enable test3 module again, which should enable both the test2 module
  // and test1 module. But, this time do it with test2 module declaring a
  // dependency on a specific version of test1 module in its info file. Make
  // sure that module_enable() still works.
  state_set('dependency_test', 'version dependency');
  backdrop_static_reset('system_rebuild_module_data');
  $result = module_enable(array('dependency_test3'));
  $this->assertTrue($result, 'module_enable() returns the correct value.');
  // Verify that the fake dependency chain was installed.
  $this->assertTrue(module_exists('dependency_test2') && module_exists('dependency_test1'), 'Dependency chain was installed by module_enable().');
  // Verify that the original module was installed.
  $this->assertTrue(module_exists('dependency_test3'), 'Module installation with version dependencies succeeded.');
  // Finally, verify that the modules were enabled in the correct order.
  $enable_order = state_get('test_module_enable_order', array());
  $first_position = array_search('dependency_test1', $enable_order);
  $second_position = array_search('dependency_test2', $enable_order);
  $third_position = array_search('dependency_test3', $enable_order);
  $first_before_second = $first_position !== FALSE && $second_position !== FALSE && $first_position < $second_position;
  $second_before_third = $second_position !== FALSE && $third_position !== FALSE && $second_position < $third_position;
  $this->assertTrue($first_before_second && $second_before_third, 'Modules were enabled in the correct order by module_enable().');
}