From e9d97f1eef493de9b9cb3ae456175ce33b5cb796 Mon Sep 17 00:00:00 2001 From: Dries Buytaert Date: Mon, 8 Jun 2009 09:23:55 +0000 Subject: [PATCH] - Patch #449198 by boombatower: cealn up test loading and related API. --- includes/registry.inc | 23 +++- modules/aggregator/aggregator.info | 1 + modules/block/block.api.php | 46 +++++++ modules/block/block.info | 1 + modules/block/block.module | 125 ++++++++++++------ modules/block/block.test | 31 +++++ modules/blog/blog.info | 1 + modules/blogapi/blogapi.info | 1 + modules/book/book.info | 1 + modules/comment/comment.info | 1 + modules/contact/contact.info | 1 + modules/dblog/dblog.info | 1 + modules/field/field.info | 1 + .../field_sql_storage/field_sql_storage.info | 1 + modules/field/modules/text/text.info | 3 +- modules/filter/filter.info | 1 + modules/forum/forum.info | 1 + modules/help/help.info | 1 + modules/locale/locale.info | 1 + modules/menu/menu.info | 1 + modules/node/node.info | 1 + modules/openid/openid.info | 1 + modules/path/path.info | 1 + modules/php/php.info | 1 + modules/poll/poll.info | 1 + modules/profile/profile.info | 1 + modules/simpletest/simpletest.info | 23 ++++ modules/simpletest/simpletest.module | 120 ++++++++++------- modules/simpletest/simpletest.pages.inc | 17 +-- modules/simpletest/tests/graph.test | 2 +- modules/statistics/statistics.info | 1 + modules/syslog/syslog.info | 1 + modules/system/system.api.php | 53 ++++++++ modules/system/system.info | 1 + modules/taxonomy/taxonomy.info | 1 + modules/tracker/tracker.info | 1 + modules/translation/translation.info | 1 + modules/trigger/trigger.info | 1 + modules/upload/upload.info | 1 + modules/user/user.info | 1 + scripts/run-tests.sh | 12 +- 41 files changed, 371 insertions(+), 114 deletions(-) diff --git a/includes/registry.inc b/includes/registry.inc index cfc7ae118a0..89de4235678 100644 --- a/includes/registry.inc +++ b/includes/registry.inc @@ -45,11 +45,19 @@ function _registry_rebuild() { system_get_files_database($modules, 'module'); // Get the list of files we are going to parse. $files = array(); - foreach ($modules as $module) { + foreach ($modules as &$module) { + $dir = dirname($module->filepath); + + // Store the module directory for use in hook_registry_files_alter(). + $module->dir = $dir; + + // Parse the .info file for all modules, reguardless of their status so the + // list of files can then be used in hook_registry_files_alter() + // implementations. + $module->info = drupal_parse_info_file($dir . '/' . $module->name . '.info'); + if ($module->status) { - // Parse .info file only for enabled modules. - $module->info = drupal_parse_info_file(dirname($module->filepath) . '/' . $module->name . '.info'); - $dir = dirname($module->filepath); + // Add files for enabled modules to the registry. foreach ($module->info['files'] as $file) { $files["$dir/$file"] = array('module' => $module->name, 'weight' => $module->weight); } @@ -59,6 +67,13 @@ function _registry_rebuild() { $files["$filename"] = array('module' => '', 'weight' => 0); } + // Allow modules to manually modify the list of files before the registry + // parses them. The $modules array provides the .info file information, which + // includes the list of files registered to each module. Any files in the + // list can then be added to the list of files that the registry will parse, + // or modify attributes of a file. + drupal_alter('registry_files', $files, $modules); + foreach (registry_get_parsed_files() as $filename => $file) { // Add the md5 to those files we've already parsed. if (isset($files[$filename])) { diff --git a/modules/aggregator/aggregator.info b/modules/aggregator/aggregator.info index fb65a7fa94a..2b75e247a52 100644 --- a/modules/aggregator/aggregator.info +++ b/modules/aggregator/aggregator.info @@ -11,3 +11,4 @@ files[] = aggregator.fetcher.inc files[] = aggregator.parser.inc files[] = aggregator.processor.inc files[] = aggregator.install +files[] = aggregator.test diff --git a/modules/block/block.api.php b/modules/block/block.api.php index 5540302e8f3..c1f5d6145b2 100644 --- a/modules/block/block.api.php +++ b/modules/block/block.api.php @@ -171,6 +171,52 @@ function hook_block_view($delta = '') { return $block; } +/** + * Act on blocks prior to rendering. + * + * This hook allows you to add, remove or modify blocks in the block list. The + * block list contains the block definitions not the rendered blocks. The blocks + * are rendered after the modules have had a chance to manipulate the block + * list. + * Alternatively you can set $block->content here, which will override the + * content of the block and prevent hook_block_view() from running. + * + * @param $blocks + * An array of $blocks, keyed by $bid + * + * This example shows how to achieve language specific visibility setting for + * blocks. + */ +function hook_block_list_alter(&$blocks) { + global $language, $theme_key; + + $result = db_query('SELECT module, delta, language FROM {my_table}'); + $block_languages = array(); + foreach ($result as $record) { + $block_languages[$record->module][$record->delta][$record->language] = TRUE; + } + + foreach ($blocks as $key => $block) { + // Any module using this alter should inspect the data before changing it, + // to ensure it is what they expect. + if ($block->theme != $theme_key || $block->status != 1) { + // This block was added by a contrib module, leave it in the list. + continue; + } + + if (!isset($block_languages[$block->module][$block->delta])) { + // No language setting for this block, leave it in the list. + continue; + } + + if (!isset($block_languages[$block->module][$block->delta][$language->language])) { + // This block should not be displayed with the active language, remove + // from the list. + unset($blocks[$key]); + } + } +} + /** * @} End of "addtogroup hooks". */ diff --git a/modules/block/block.info b/modules/block/block.info index a74f5d7213e..bb14187aa35 100644 --- a/modules/block/block.info +++ b/modules/block/block.info @@ -8,3 +8,4 @@ core = 7.x files[] = block.module files[] = block.admin.inc files[] = block.install +files[] = block.test diff --git a/modules/block/block.module b/modules/block/block.module index 13e9821ada0..80073729831 100644 --- a/modules/block/block.module +++ b/modules/block/block.module @@ -586,30 +586,64 @@ function block_list($region) { * Load blocks information from the database. */ function _block_load_blocks() { - global $user, $theme_key; + global $theme_key; - $blocks = array(); - $rids = array_keys($user->roles); $query = db_select('block', 'b'); - $query->leftJoin('block_role', 'r', 'b.module = r.module AND b.delta = r.delta'); $result = $query - ->distinct() ->fields('b') ->condition('b.theme', $theme_key) ->condition('b.status', 1) - ->condition(db_or() - ->condition('r.rid', $rids, 'IN') - ->isNull('r.rid') - ) ->orderBy('b.region') ->orderBy('b.weight') ->orderBy('b.module') ->addTag('block_load') ->execute(); - foreach ($result as $block) { - if (!isset($blocks[$block->region])) { - $blocks[$block->region] = array(); + + $block_list = $result->fetchAllAssoc('bid'); + // Allow modules to modify the block list. + drupal_alter('block_list', $block_list); + + $blocks = array(); + foreach ($block_list as $block) { + $blocks[$block->region]["{$block->module}_{$block->delta}"] = $block; + } + return $blocks; +} + +/** + * Implement hook_block_list_alter(). + * + * Check the page, role and user specific visibilty settings. Remove the block + * if the visibility conditions are not met. + */ +function block_block_list_alter(&$blocks) { + global $user, $theme_key; + + // Build an array of roles for each block. + $block_roles = array(); + $result = db_query('SELECT module, delta, rid FROM {block_role}'); + foreach ($result as $record) { + $block_roles[$record->module][$record->delta][] = $record->rid; + } + + foreach ($blocks as $key => $block) { + if ($block->theme != $theme_key || $block->status != 1) { + // This block was added by a contrib module, leave it in the list. + continue; } + + // If a block has no roles associated, it is displayed for every role. + // For blocks with roles associated, if none of the user's roles matches + // the settings from this block, remove it from the block list. + if (!isset($block_roles[$block->module][$block->delta])) { + // No roles associated. + } + elseif (!array_intersect($block_roles[$block->module][$block->delta], array_keys($user->roles))) { + // No match. + unset($blocks[$key]); + continue; + } + // Use the user's block visibility setting, if necessary. if ($block->custom != 0) { if ($user->uid && isset($user->block[$block->module][$block->delta])) { @@ -622,6 +656,10 @@ function _block_load_blocks() { else { $enabled = TRUE; } + if (!$enabled) { + unset($blocks[$key]); + continue; + } // Match path if necessary. if ($block->pages) { @@ -647,12 +685,10 @@ function _block_load_blocks() { else { $page_match = TRUE; } - $block->enabled = $enabled; - $block->page_match = $page_match; - $blocks[$block->region]["{$block->module}_{$block->delta}"] = $block; + if (!$page_match) { + unset($blocks[$key]); + } } - - return $blocks; } /** @@ -668,38 +704,39 @@ function _block_render_blocks($region_blocks) { foreach ($region_blocks as $key => $block) { // Render the block content if it has not been created already. if (!isset($block->content)) { - // Erase the block from the static array - we'll put it back if it has content. + // Erase the block from the static array - we'll put it back if it has + // content. unset($region_blocks[$key]); - if ($block->enabled && $block->page_match) { - // Try fetching the block from cache. Block caching is not compatible with - // node_access modules. We also preserve the submission of forms in blocks, - // by fetching from cache only if the request method is 'GET' (or 'HEAD'). - if (!count(module_implements('node_grants')) && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD') && ($cid = _block_get_cache_id($block)) && ($cache = cache_get($cid, 'cache_block'))) { - $array = $cache->data; - } - else { - $array = module_invoke($block->module, 'block_view', $block->delta); - if (isset($cid)) { - cache_set($cid, $array, 'cache_block', CACHE_TEMPORARY); - } + // Try fetching the block from cache. Block caching is not compatible + // with node_access modules. We also preserve the submission of forms in + // blocks, by fetching from cache only if the request method is 'GET' + // (or 'HEAD'). + if (!count(module_implements('node_grants')) && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD') && ($cid = _block_get_cache_id($block)) && ($cache = cache_get($cid, 'cache_block'))) { + $array = $cache->data; + } + else { + $array = module_invoke($block->module, 'block_view', $block->delta); + if (isset($cid)) { + cache_set($cid, $array, 'cache_block', CACHE_TEMPORARY); } + } - if (isset($array) && is_array($array)) { - foreach ($array as $k => $v) { - $block->$k = $v; - } + if (isset($array) && is_array($array)) { + foreach ($array as $k => $v) { + $block->$k = $v; } - if (isset($block->content) && $block->content) { - // Override default block title if a custom display title is present. - if ($block->title) { - // Check plain here to allow module generated titles to keep any markup. - $block->subject = $block->title == '' ? '' : check_plain($block->title); - } - if (!isset($block->subject)) { - $block->subject = ''; - } - $region_blocks["{$block->module}_{$block->delta}"] = $block; + } + if (isset($block->content) && $block->content) { + // Override default block title if a custom display title is present. + if ($block->title) { + // Check plain here to allow module generated titles to keep any + // markup. + $block->subject = $block->title == '' ? '' : check_plain($block->title); } + if (!isset($block->subject)) { + $block->subject = ''; + } + $region_blocks["{$block->module}_{$block->delta}"] = $block; } } } diff --git a/modules/block/block.test b/modules/block/block.test index 9dcd199b6f7..73d256ac003 100644 --- a/modules/block/block.test +++ b/modules/block/block.test @@ -99,6 +99,37 @@ class BlockTestCase extends DrupalWebTestCase { $this->assertRaw('

Full HTML

', t('Box successfully being displayed using Full HTML.')); } + /** + * Test block visibility. + */ + function testBlockVisibility() { + $block = array(); + $block['title'] = 'Syndicate'; + $block['module'] = 'node'; + $block['delta'] = 'syndicate'; + + // Set the block to be hidden on any user path, and to be shown only to + // authenticated users. + $edit = array(); + $edit['pages'] = 'user*'; + $edit['roles[2]'] = TRUE; + $this->drupalPost('admin/build/block/configure/' . $block['module'] . '/' . $block['delta'], $edit, t('Save block')); + + // Move block to the left sidebar. + $this->moveBlockToRegion($block, $this->regions[1]); + + $this->drupalGet(''); + $this->assertText('Syndicate', t('Block was displayed on the front page.')); + + $this->drupalGet('user*'); + $this->assertNoText('Syndicate', t('Block was not displayed according to block visibility rules.')); + + // Confirm that the block is not displayed to anonymous users. + $this->drupalLogout(); + $this->drupalGet(''); + $this->assertNoText('Syndicate', t('Block was not displayed to anonymous users.')); + } + /** * Test configuring and moving a module-define block to specific regions. */ diff --git a/modules/blog/blog.info b/modules/blog/blog.info index 2d047f304c9..938993c0e47 100644 --- a/modules/blog/blog.info +++ b/modules/blog/blog.info @@ -7,3 +7,4 @@ version = VERSION core = 7.x files[] = blog.module files[] = blog.pages.inc +files[] = blog.test diff --git a/modules/blogapi/blogapi.info b/modules/blogapi/blogapi.info index 257ffd25b9e..87e365e5bc7 100644 --- a/modules/blogapi/blogapi.info +++ b/modules/blogapi/blogapi.info @@ -7,3 +7,4 @@ version = VERSION core = 7.x files[] = blogapi.module files[] = blogapi.install +files[] = blogapi.test diff --git a/modules/book/book.info b/modules/book/book.info index e4445800590..b30b4a59eb4 100644 --- a/modules/book/book.info +++ b/modules/book/book.info @@ -9,3 +9,4 @@ files[] = book.module files[] = book.admin.inc files[] = book.pages.inc files[] = book.install +files[] = book.test diff --git a/modules/comment/comment.info b/modules/comment/comment.info index 76237130745..71a62e3ed44 100644 --- a/modules/comment/comment.info +++ b/modules/comment/comment.info @@ -9,3 +9,4 @@ files[] = comment.module files[] = comment.admin.inc files[] = comment.pages.inc files[] = comment.install +files[] = comment.test diff --git a/modules/contact/contact.info b/modules/contact/contact.info index 750e18176ba..fda41ae0f52 100644 --- a/modules/contact/contact.info +++ b/modules/contact/contact.info @@ -8,3 +8,4 @@ files[] = contact.module files[] = contact.admin.inc files[] = contact.pages.inc files[] = contact.install +files[] = contact.test diff --git a/modules/dblog/dblog.info b/modules/dblog/dblog.info index 5e9d284a73a..6b9f82390c0 100644 --- a/modules/dblog/dblog.info +++ b/modules/dblog/dblog.info @@ -7,3 +7,4 @@ core = 7.x files[] = dblog.module files[] = dblog.admin.inc files[] = dblog.install +files[] = dblog.test diff --git a/modules/field/field.info b/modules/field/field.info index 76f6687b373..9c06c176083 100644 --- a/modules/field/field.info +++ b/modules/field/field.info @@ -11,5 +11,6 @@ files[] = field.info.inc files[] = field.default.inc files[] = field.attach.inc files[] = field.form.inc +files[] = field.test dependencies[] = field_sql_storage required = TRUE diff --git a/modules/field/modules/field_sql_storage/field_sql_storage.info b/modules/field/modules/field_sql_storage/field_sql_storage.info index 4d0f4a57571..5587fbe32c1 100644 --- a/modules/field/modules/field_sql_storage/field_sql_storage.info +++ b/modules/field/modules/field_sql_storage/field_sql_storage.info @@ -6,4 +6,5 @@ version = VERSION core = 7.x files[] = field_sql_storage.module files[] = field_sql_storage.install +files[] = field_sql_storage.test required = TRUE diff --git a/modules/field/modules/text/text.info b/modules/field/modules/text/text.info index 328bfc3f8ec..17a6760254b 100644 --- a/modules/field/modules/text/text.info +++ b/modules/field/modules/text/text.info @@ -4,4 +4,5 @@ description = Defines simple text field types. package = Core - fields version = VERSION core = 7.x -files[]=text.module +files[] = text.module +files[] = text.test diff --git a/modules/filter/filter.info b/modules/filter/filter.info index 05d996a0b8c..ecd3de188fb 100644 --- a/modules/filter/filter.info +++ b/modules/filter/filter.info @@ -8,4 +8,5 @@ files[] = filter.module files[] = filter.admin.inc files[] = filter.pages.inc files[] = filter.install +files[] = filter.test required = TRUE diff --git a/modules/forum/forum.info b/modules/forum/forum.info index 27c588bc792..ff4621a5f4c 100644 --- a/modules/forum/forum.info +++ b/modules/forum/forum.info @@ -10,3 +10,4 @@ files[] = forum.module files[] = forum.admin.inc files[] = forum.pages.inc files[] = forum.install +files[] = forum.test diff --git a/modules/help/help.info b/modules/help/help.info index e5ece02c6fc..4c84b26219a 100644 --- a/modules/help/help.info +++ b/modules/help/help.info @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = help.module files[] = help.admin.inc +files[] = help.test diff --git a/modules/locale/locale.info b/modules/locale/locale.info index 2638c4960b3..02b86521d5d 100644 --- a/modules/locale/locale.info +++ b/modules/locale/locale.info @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = locale.module files[] = locale.install +files[] = locale.test diff --git a/modules/menu/menu.info b/modules/menu/menu.info index 31bd386e65f..f3db2a75b7e 100644 --- a/modules/menu/menu.info +++ b/modules/menu/menu.info @@ -7,3 +7,4 @@ core = 7.x files[] = menu.module files[] = menu.admin.inc files[] = menu.install +files[] = menu.test diff --git a/modules/node/node.info b/modules/node/node.info index 975b5dcc568..2f62a99013b 100644 --- a/modules/node/node.info +++ b/modules/node/node.info @@ -9,4 +9,5 @@ files[] = content_types.inc files[] = node.admin.inc files[] = node.pages.inc files[] = node.install +files[] = node.test required = TRUE diff --git a/modules/openid/openid.info b/modules/openid/openid.info index 4d14448a0b7..9335fa8bac6 100644 --- a/modules/openid/openid.info +++ b/modules/openid/openid.info @@ -9,3 +9,4 @@ files[] = openid.inc files[] = openid.pages.inc files[] = xrds.inc files[] = openid.install +files[] = openid.test diff --git a/modules/path/path.info b/modules/path/path.info index 7453923d899..ee05f40f0bc 100644 --- a/modules/path/path.info +++ b/modules/path/path.info @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = path.module files[] = path.admin.inc +files[] = path.test diff --git a/modules/php/php.info b/modules/php/php.info index e353bf9b8d5..2f158834039 100644 --- a/modules/php/php.info +++ b/modules/php/php.info @@ -6,3 +6,4 @@ version = VERSION core = 7.x files[] = php.module files[] = php.install +files[] = php.test diff --git a/modules/poll/poll.info b/modules/poll/poll.info index 9aff7b50234..d59cc9b93f8 100644 --- a/modules/poll/poll.info +++ b/modules/poll/poll.info @@ -7,3 +7,4 @@ core = 7.x files[] = poll.module files[] = poll.pages.inc files[] = poll.install +files[] = poll.test diff --git a/modules/profile/profile.info b/modules/profile/profile.info index 522284781f6..7e6e511ec1d 100644 --- a/modules/profile/profile.info +++ b/modules/profile/profile.info @@ -8,3 +8,4 @@ files[] = profile.module files[] = profile.admin.inc files[] = profile.pages.inc files[] = profile.install +files[] = profile.test diff --git a/modules/simpletest/simpletest.info b/modules/simpletest/simpletest.info index 0fefa967d24..a90e5dd2c85 100644 --- a/modules/simpletest/simpletest.info +++ b/modules/simpletest/simpletest.info @@ -7,3 +7,26 @@ core = 7.x files[] = simpletest.module files[] = simpletest.pages.inc files[] = simpletest.install +files[] = simpletest.test +files[] = drupal_web_test_case.php + +; Tests in tests directory. +files[] = tests/actions.test +files[] = tests/batch.test +files[] = tests/bootstrap.test +files[] = tests/cache.test +files[] = tests/common.test +files[] = tests/database_test.test +files[] = tests/error.test +files[] = tests/file.test +files[] = tests/form.test +files[] = tests/graph.test +files[] = tests/image.test +files[] = tests/menu.test +files[] = tests/module.test +files[] = tests/registry.test +files[] = tests/schema.test +files[] = tests/session.test +files[] = tests/theme.test +files[] = tests/unicode.test +files[] = tests/xmlrpc.test diff --git a/modules/simpletest/simpletest.module b/modules/simpletest/simpletest.module index 1300c24169d..630ddb3f3da 100644 --- a/modules/simpletest/simpletest.module +++ b/modules/simpletest/simpletest.module @@ -139,9 +139,6 @@ function simpletest_run_tests($test_list, $reporter = 'drupal') { * Batch operation callback. */ function _simpletest_batch_operation($test_list_init, $test_id, &$context) { - // Ensure that all classes are loaded before we unserialize some instances. - simpletest_get_all_tests(); - // Get working values. if (!isset($context['sandbox']['max'])) { // First iteration: initialize working values. @@ -200,65 +197,94 @@ function _simpletest_batch_finished($success, $results, $operations, $elapsed) { } /** - * Get a list of all of the tests. + * Get a list of all of the tests provided by the system. + * + * The list of test classes is loaded from the registry where it looks for + * files ending in ".test". Once loaded the test list is cached and stored in + * a static variable. In order to list tests provided by disabled modules + * hook_registry_files_alter() is used to forcefully add them to the registry. * * @return - * An array of tests, with the class name as the keys and the instantiated - * versions of the classes as the values. + * An array of tests keyed with the groups specified in each of the tests + * getInfo() method and then keyed by the test class. An example of the array + * structure is provided below. + * + * @code + * $groups['Blog'] => array( + * 'BlogTestCase' => array( + * 'name' => 'Blog functionality', + * 'description' => 'Create, view, edit, delete, ...', + * 'group' => 'Blog', + * ), + * ); + * @endcode + * @see simpletest_registry_files_alter() */ -function simpletest_get_all_tests() { - static $classes; - if (!isset($classes)) { - require_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'simpletest') . '/drupal_web_test_case.php'; - $files = array(); - foreach (array_keys(system_get_module_data()) as $module) { - $module_path = drupal_get_path('module', $module); - $test = $module_path . "/$module.test"; - if (file_exists($test)) { - $files[] = $test; - } +function simpletest_test_get_all() { + $groups = &drupal_static(__FUNCTION__); - $tests_directory = $module_path . '/tests'; - if (is_dir($tests_directory)) { - foreach (file_scan_directory($tests_directory, '/\.test$/') as $file) { - $files[] = $file->filepath; + if (!$groups) { + // Load test information from cache if available, otherwise retrieve the + // information from each tests getInfo() method. + if ($cache = cache_get('simpletest', 'cache')) { + $groups = $cache->data; + } + else { + // Select all clases in files ending with .test. + $classes = db_select('registry') + ->fields('registry', array('name')) + ->condition('type', 'class') + ->condition('filename', '%.test', 'LIKE') + ->execute(); + + $groups = array(); + + // Check that each class has a getInfo() method and store the information + // in an array keyed with the group specified in the test information. + foreach ($classes as $class) { + $class = $class->name; + if (class_exists($class) && method_exists($class, 'getInfo')) { + // Valid test class, retrieve test information. + $info = call_user_func(array($class, 'getInfo')); + + // Initialize test groups. + if (!isset($groups[$info['group']])) { + $groups[$info['group']] = array(); + } + $groups[$info['group']][$class] = $info; } } - } - - $existing_classes = get_declared_classes(); - foreach ($files as $file) { - include_once DRUPAL_ROOT . '/' . $file; - } - $classes = array_values(array_diff(get_declared_classes(), $existing_classes)); - foreach ($classes as $key => $class) { - if (!is_subclass_of($class, 'DrupalTestCase') || !method_exists($class, 'getInfo')) { - unset($classes[$key]); + // Sort the groups and tests within the groups by name. + uksort($groups, 'strnatcasecmp'); + foreach ($groups as $group => &$tests) { + uksort($tests, 'strnatcasecmp'); } + + cache_set('simpletest', $groups); } } - if (count($classes) == 0) { - drupal_set_message('No test cases found.', 'error'); - return FALSE; - } - return $classes; + return $groups; } /** - * Categorize the tests into groups. + * Implementation of hook_registry_files_alter(). * - * @param $tests - * A list of tests from simpletest_get_all_tests. - * @see simpletest_get_all_tests. + * Add the test files for disabled modules so that we get a list containing + * all the avialable tests. */ -function simpletest_categorize_tests($tests) { - $groups = array(); - foreach ($tests as $test) { - $info = call_user_func(array($test, 'getInfo')); - $groups[$info['group']][$test] = $info; +function simpletest_registry_files_alter(&$files, $modules) { + foreach ($modules as $module) { + // Only add test files for disabled modules, as enabled modules should + // already include any test files they provide. + if (!$module->status) { + $dir = $module->dir; + foreach ($module->info['files'] as $file) { + if (substr($file, -5) == '.test') { + $files["$dir/$file"] = array('module' => $module->name, 'weight' => $module->weight); + } + } + } } - uksort($groups, 'strnatcasecmp'); - return $groups; } /** diff --git a/modules/simpletest/simpletest.pages.inc b/modules/simpletest/simpletest.pages.inc index 24a779348cf..2df1765fa76 100644 --- a/modules/simpletest/simpletest.pages.inc +++ b/modules/simpletest/simpletest.pages.inc @@ -12,10 +12,6 @@ function simpletest_test_form() { $form = array(); - // Categorize the tests for display. - $uncategorized_tests = simpletest_get_all_tests(); - $tests = simpletest_categorize_tests($uncategorized_tests); - $form['tests'] = array( '#type' => 'fieldset', '#title' => t('Tests'), @@ -27,13 +23,14 @@ function simpletest_test_form() { ); // Generate the list of tests arranged by group. - foreach ($tests as $group_name => $test_group) { - $form['tests']['table'][$group_name] = array( + $groups = simpletest_test_get_all(); + foreach ($groups as $group => $tests) { + $form['tests']['table'][$group] = array( '#collapsed' => TRUE, ); - foreach ($test_group as $class => $info) { - $form['tests']['table'][$group_name][$class] = array( + foreach ($tests as $class => $info) { + $form['tests']['table'][$group][$class] = array( '#type' => 'checkbox', '#title' => $info['name'], '#description' => $info['description'], @@ -166,9 +163,6 @@ function theme_simpletest_test_table($table) { * Run selected tests. */ function simpletest_test_form_submit($form, &$form_state) { - // Ensure that all classes are loaded before we create instances to get test information and run. - simpletest_get_all_tests(); - // Get list of tests. $tests_list = array(); foreach ($form_state['values'] as $class_name => $value) { @@ -200,7 +194,6 @@ function simpletest_result_form(&$form_state, $test_id) { // Load all classes and include CSS. drupal_add_css(drupal_get_path('module', 'simpletest') . '/simpletest.css'); - simpletest_get_all_tests(); // Keep track of which test cases passed or failed. $filter = array( diff --git a/modules/simpletest/tests/graph.test b/modules/simpletest/tests/graph.test index a5ed9314b7d..b3270f843a9 100644 --- a/modules/simpletest/tests/graph.test +++ b/modules/simpletest/tests/graph.test @@ -23,7 +23,7 @@ class GraphUnitTest extends DrupalUnitTestCase { */ function testDepthFirstSearch() { // Provoke the inclusion of graph.inc. - drupal_function_exists('drupal_depth_first_search'); + require_once 'includes/graph.inc'; // The sample graph used is: // 1 --> 2 --> 3 5 ---> 6 diff --git a/modules/statistics/statistics.info b/modules/statistics/statistics.info index aaeb7d0152b..a3a509124d5 100644 --- a/modules/statistics/statistics.info +++ b/modules/statistics/statistics.info @@ -8,3 +8,4 @@ files[] = statistics.module files[] = statistics.admin.inc files[] = statistics.pages.inc files[] = statistics.install +files[] = statistics.test diff --git a/modules/syslog/syslog.info b/modules/syslog/syslog.info index 55ff66b26d7..ff6246aee15 100644 --- a/modules/syslog/syslog.info +++ b/modules/syslog/syslog.info @@ -5,3 +5,4 @@ package = Core version = VERSION core = 7.x files[] = syslog.module +files[] = syslog.test diff --git a/modules/system/system.api.php b/modules/system/system.api.php index 0efcedbc353..1349a7b8fba 100644 --- a/modules/system/system.api.php +++ b/modules/system/system.api.php @@ -1700,6 +1700,59 @@ function hook_disable() { mymodule_cache_rebuild(); } +/** + * Perform necessary alterations to the list of files parsed by the registry. + * + * Modules can manually modify the list of files before the registry parses + * them. The $modules array provides the .info file information, which includes + * the list of files registered to each module. Any files in the list can then + * be added to the list of files that the registry will parse, or modify + * attributes of a file. + * + * A necessary alteration made by the core SimpleTest module is to force .test + * files provided by disabled modules into the list of files parsed by the + * registry. + * + * @param $files + * List of files to be parsed by the registry. The list will contain + * files found in each enabled module's info file and the core includes + * directory. The array is keyed by the file path and contains an array of + * the related module's name and weight as used internally by + * _registry_rebuild() and related functions. + * + * For example: + * @code + * $files["modules/system/system.module"] = array( + * 'module' => 'system', + * 'weight' => 0, + * ); + * @endcode + * @param $modules + * List of all the modules provided as returned by drupal_system_listing(). + * The list also contains the .info file information in the property 'info'. + * An additional 'dir' property has been added to the module information + * which provides the path to the directory in which the module resides. The + * example shows how to take advantage of the property both properties. + * + * @see _registry_rebuild() + * @see drupal_system_listing() + * @see simpletest_test_get_all() + */ +function hook_registry_files_alter(&$files, $module_cache) { + foreach ($modules as $module) { + // Only add test files for disabled modules, as enabled modules should + // already include any test files they provide. + if (!$module->status) { + $dir = $module->dir; + foreach ($module->info['files'] as $file) { + if (substr($file, -5) == '.test') { + $files["$dir/$file"] = array('module' => $module->name, 'weight' => $module->weight); + } + } + } + } +} + /** * @} End of "addtogroup hooks". */ diff --git a/modules/system/system.info b/modules/system/system.info index 0afcdaf9a20..9c93a096094 100644 --- a/modules/system/system.info +++ b/modules/system/system.info @@ -9,4 +9,5 @@ files[] = system.admin.inc files[] = system.queue.inc files[] = image.gd.inc files[] = system.install +files[] = system.test required = TRUE diff --git a/modules/taxonomy/taxonomy.info b/modules/taxonomy/taxonomy.info index 4d05fc44291..35dfa148056 100644 --- a/modules/taxonomy/taxonomy.info +++ b/modules/taxonomy/taxonomy.info @@ -8,3 +8,4 @@ files[] = taxonomy.module files[] = taxonomy.admin.inc files[] = taxonomy.pages.inc files[] = taxonomy.install +files[] = taxonomy.test diff --git a/modules/tracker/tracker.info b/modules/tracker/tracker.info index b26cff0556e..f70550d371f 100644 --- a/modules/tracker/tracker.info +++ b/modules/tracker/tracker.info @@ -7,3 +7,4 @@ version = VERSION core = 7.x files[] = tracker.module files[] = tracker.pages.inc +files[] = tracker.test diff --git a/modules/translation/translation.info b/modules/translation/translation.info index 63c2c1c63a3..3f6841c2a93 100644 --- a/modules/translation/translation.info +++ b/modules/translation/translation.info @@ -7,3 +7,4 @@ version = VERSION core = 7.x files[] = translation.module files[] = translation.pages.inc +files[] = translation.test diff --git a/modules/trigger/trigger.info b/modules/trigger/trigger.info index 9ba7439f467..e097d59deed 100644 --- a/modules/trigger/trigger.info +++ b/modules/trigger/trigger.info @@ -7,3 +7,4 @@ core = 7.x files[] = trigger.module files[] = trigger.admin.inc files[] = trigger.install +files[] = trigger.test diff --git a/modules/upload/upload.info b/modules/upload/upload.info index 92d04e09a70..d5039f5214a 100644 --- a/modules/upload/upload.info +++ b/modules/upload/upload.info @@ -7,3 +7,4 @@ core = 7.x files[] = upload.module files[] = upload.admin.inc files[] = upload.install +files[] = upload.test diff --git a/modules/user/user.info b/modules/user/user.info index 98ef2dfb002..d4c24fa7722 100644 --- a/modules/user/user.info +++ b/modules/user/user.info @@ -8,4 +8,5 @@ files[] = user.module files[] = user.admin.inc files[] = user.pages.inc files[] = user.install +files[] = user.test required = TRUE diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh index 795c6788600..ada07c75c9e 100755 --- a/scripts/run-tests.sh +++ b/scripts/run-tests.sh @@ -44,8 +44,11 @@ if ($args['clean']) { } // Load SimpleTest files. -$all_tests = simpletest_get_all_tests(); -$groups = simpletest_categorize_tests($all_tests); +$groups = simpletest_test_get_all(); +$all_tests = array(); +foreach ($groups as $group => $tests) { + $all_tests = array_merge($all_tests, array_keys($tests)); +} $test_list = array(); if ($args['list']) { @@ -54,8 +57,8 @@ if ($args['list']) { echo "-------------------------------\n\n"; foreach ($groups as $group => $tests) { echo $group . "\n"; - foreach ($tests as $class_name => $info) { - echo " - " . $info['name'] . ' (' . $class_name . ')' . "\n"; + foreach ($tests as $class => $info) { + echo " - " . $info['name'] . ' (' . $class . ')' . "\n"; } } exit; @@ -339,7 +342,6 @@ function simpletest_script_execute_batch() { * Run a single test (assume a Drupal bootstrapped environment). */ function simpletest_script_run_one_test($test_id, $test_class) { - simpletest_get_all_tests(); $test = new $test_class($test_id); $test->run(); $info = $test->getInfo();