Line # | Frequency | Source Line |
1 | | <?php
|
2 | | // $Id: drupal_unit_tests.php,v 1.17 2008/04/03 19:57:15 boombatower Exp $
|
3 | |
|
4 | | /**
|
5 | | * Implementes getTestInstances to allow access to the test objects from outside
|
6 | | */
|
7 | | class DrupalTestSuite extends TestSuite {
|
8 | | var $_cleanupModules = array();
|
9 | |
|
10 | | function DrupalTestSuite($label) {
|
11 | 1 | $this->TestSuite($label);
|
12 | | }
|
13 | |
|
14 | | /**
|
15 | | * @return array of instantiated tests that this GroupTests holds
|
16 | | */
|
17 | | function getTestInstances() {
|
18 | | for ($i = 0, $count = count($this->_test_cases); $i < $count; $i++) {
|
19 | | if (is_string($this->_test_cases[$i])) {
|
20 | | $class = $this->_test_cases[$i];
|
21 | | $this->_test_cases[$i] = &new $class();
|
22 | | }
|
23 | | }
|
24 | | return $this->_test_cases;
|
25 | | }
|
26 | | }
|
27 | |
|
28 | | class DrupalUnitTests extends DrupalTestSuite {
|
29 | | /**
|
30 | | * Constructor
|
31 | | * @param array $class_list list containing the classes of tests to be processed
|
32 | | * default: NULL - run all tests
|
33 | | */
|
34 | | function DrupalUnitTests($class_list = NULL) {
|
35 | 1 | static $classes;
|
36 | 1 | $this->DrupalTestSuite('Drupal Unit Tests');
|
37 | |
|
38 | | /* Tricky part to avoid double inclusion */
|
39 | 1 | if (!$classes) {
|
40 | |
|
41 | | $files = array();
|
42 | | foreach (module_list() as $module) {
|
43 | | $module_path = drupal_get_path('module', $module);
|
44 | | if (file_exists($module_path .'/tests/')) {
|
45 | | $dir = $module_path .'/tests';
|
46 | | $tests = file_scan_directory($dir, '\.test$');
|
47 | | $files = array_merge($files, $tests);
|
48 | | }
|
49 | | }
|
50 | | $files = array_keys($files);
|
51 | |
|
52 | | $existing_classes = get_declared_classes();
|
53 | | foreach ($files as $file) {
|
54 | | include_once($file);
|
55 | | }
|
56 | | $classes = array_diff(get_declared_classes(), $existing_classes);
|
57 | | }
|
58 | 1 | if (!is_null($class_list)) {
|
59 | 1 | $classes = $class_list;
|
60 | | }
|
61 | 1 | if (count($classes) == 0) {
|
62 | | drupal_set_message('No test cases found.', 'error');
|
63 | | return;
|
64 | | }
|
65 | | $groups = array();
|
66 | 1 | foreach ($classes as $class) {
|
67 | 1 | if (!is_subclass_of($class, 'DrupalTestCase')) {
|
68 | | continue;
|
69 | | }
|
70 | 1 | $this->_addClassToGroups($groups, $class);
|
71 | | }
|
72 | 1 | foreach ($groups as $group_name => $group) {
|
73 | 1 | $group_test = &new DrupalTestSuite($group_name);
|
74 | 1 | foreach ($group as $key => $v) {
|
75 | 1 | $group_test->addTestCase($group[$key]);
|
76 | | }
|
77 | 1 | $this->addTestCase($group_test);
|
78 | | }
|
79 | | }
|
80 | |
|
81 | | /**
|
82 | | * Adds a class to a groups array specified by the getInfo of the group
|
83 | | * @param array $groups Group of categorized tests
|
84 | | * @param string $class Name of a class
|
85 | | */
|
86 | | function _addClassToGroups(&$groups, $class) {
|
87 | 1 | $test = &new $class();
|
88 | 1 | if (method_exists($test, 'getInfo')) {
|
89 | 1 | $info = $test->getInfo();
|
90 | 1 | $groups[$info['group']][] = $test;
|
91 | | }
|
92 | | }
|
93 | |
|
94 | | /**
|
95 | | * Invokes run() on all of the held test cases, instantiating
|
96 | | * them if necessary.
|
97 | | * The Drupal version uses paintHeader instead of paintGroupStart
|
98 | | * to avoid collapsing of the very top level.
|
99 | | *
|
100 | | * @param SimpleReporter $reporter Current test reporter.
|
101 | | * @access public
|
102 | | */
|
103 | | function run(&$reporter) {
|
104 | 1 | cache_clear_all();
|
105 | 1 | @set_time_limit(0);
|
106 | 1 | ignore_user_abort(true);
|
107 | |
|
108 | | // Disable devel output, check simpletest settings page
|
109 | 1 | if (!variable_get('simpletest_devel', false)) {
|
110 | 1 | $GLOBALS['devel_shutdown'] = FALSE;
|
111 | | }
|
112 | |
|
113 | 1 | $result = parent::run($reporter);
|
114 | |
|
115 | | // Restores modules
|
116 | 1 | foreach ($this->_cleanupModules as $name => $status) {
|
117 | | db_query("UPDATE {system} SET status = %d WHERE name = '%s' AND type = 'module'", $status, $name);
|
118 | | }
|
119 | 1 | $this->_cleanupModules = array();
|
120 | |
|
121 | 1 | return $result;
|
122 | | }
|
123 | |
|
124 | | /**
|
125 | | * Enables a drupal module
|
126 | | * @param string $name name of the module
|
127 | | * @return boolean success
|
128 | | */
|
129 | | function drupalModuleEnable($name) {
|
130 | | if (module_exists($name)) {
|
131 | | return TRUE;
|
132 | | }
|
133 | | include_once './includes/install.inc';
|
134 | | module_rebuild_cache(); // Rebuild the module cache
|
135 | | if (drupal_get_installed_schema_version($name, TRUE) == SCHEMA_UNINSTALLED) {
|
136 | | drupal_install_modules(array($name));
|
137 | | }
|
138 | | else {
|
139 | | $try = module_enable(array($name));
|
140 | | }
|
141 | |
|
142 | | if(module_exists($name)) {
|
143 | | if (!isset($this->_cleanupModules[$name])) {
|
144 | | $this->_cleanupModules[$name] = 0;
|
145 | | return TRUE;
|
146 | | }
|
147 | | }
|
148 | | else {
|
149 | | die("required module $name could not be enabled (probably file does not exist)");
|
150 | | }
|
151 | | }
|
152 | |
|
153 | |
|
154 | | /**
|
155 | | * Disables a drupal module
|
156 | | * @param string $name name of the module
|
157 | | * @return boolean success
|
158 | | */
|
159 | | function drupalModuleDisable($name) {
|
160 | | if (!module_exists($name)) {
|
161 | | return TRUE;
|
162 | | }
|
163 | | /* Update table */
|
164 | | db_query("UPDATE {system} SET status = 0 WHERE name = '%s' AND type = 'module'", $name);
|
165 | | if (db_affected_rows()) {
|
166 | | /* Make sure not overwriting when double switching */
|
167 | | if (!isset($this->_cleanupModules[$name])) {
|
168 | | $this->_cleanupModules[$name] = 1;
|
169 | | }
|
170 | | /* refresh module_list */
|
171 | | module_list(TRUE, FALSE);
|
172 | | return TRUE;
|
173 | | }
|
174 | | die("incompatible module $name could not be disabled for unknown reason");
|
175 | | }
|
176 | | }
|