Merge pull request #4818 from pratikshad/CRM-15770
[civicrm-core.git] / tests / phpunit / CRM / Extension / Manager / ModuleTest.php
1 <?php
2
3 require_once 'CiviTest/CiviUnitTestCase.php';
4
5 /**
6 * Class CRM_Extension_Manager_ModuleTest
7 */
8 class CRM_Extension_Manager_ModuleTest extends CiviUnitTestCase {
9 //@todo make BAO enotice compliant & remove the line below
10 // WARNING - NEVER COPY & PASTE $_eNoticeCompliant = FALSE
11 // new test classes should be compliant.
12 public $_eNoticeCompliant = FALSE;
13 public function setUp() {
14 parent::setUp();
15 // $query = "INSERT INTO civicrm_domain ( name, version ) VALUES ( 'domain', 3 )";
16 // $result = CRM_Core_DAO::executeQuery($query);
17 global $_test_extension_manager_moduletest_counts;
18 $_test_extension_manager_moduletest_counts = array();
19 $this->basedir = $this->createTempDir('ext-');
20 $this->system = new CRM_Extension_System(array(
21 'extensionsDir' => $this->basedir,
22 'extensionsURL' => 'http://testbase/',
23 ));
24 $this->setExtensionSystem($this->system);
25 }
26
27 public function tearDown() {
28 parent::tearDown();
29 $this->system = NULL;
30 }
31
32 /**
33 * Install an extension with a valid type name
34 */
35 public function testInstallDisableUninstall() {
36 $manager = $this->system->getManager();
37 $this->assertModuleActiveByName(FALSE, 'moduletest');
38
39 $manager->install(array('test.extension.manager.moduletest'));
40 $this->assertHookCounts('moduletest', array(
41 'install' => 1,
42 'postInstall' => 1,
43 'enable' => 1,
44 'disable' => 0,
45 'uninstall' => 0,
46 ));
47 $this->assertModuleActiveByName(TRUE, 'moduletest');
48 $this->assertModuleActiveByKey(TRUE, 'test.extension.manager.moduletest');
49
50 $manager->disable(array('test.extension.manager.moduletest'));
51 $this->assertHookCounts('moduletest', array(
52 'install' => 1,
53 'postInstall' => 1,
54 'enable' => 1,
55 'disable' => 1,
56 'uninstall' => 0,
57 ));
58 $this->assertModuleActiveByName(FALSE, 'moduletest');
59 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.moduletest');
60
61 $manager->uninstall(array('test.extension.manager.moduletest'));
62 $this->assertHookCounts('moduletest', array(
63 'install' => 1,
64 'postInstall' => 1,
65 'enable' => 1,
66 'disable' => 1,
67 'uninstall' => 1,
68 ));
69 $this->assertModuleActiveByName(FALSE, 'moduletest');
70 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.moduletest');
71 }
72
73 /**
74 * Install an extension with a valid type name
75 */
76 public function testInstallDisableEnable() {
77 $manager = $this->system->getManager();
78 $this->assertModuleActiveByName(FALSE, 'moduletest');
79 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.moduletest');
80
81 $manager->install(array('test.extension.manager.moduletest'));
82 $this->assertHookCounts('moduletest', array(
83 'install' => 1,
84 'enable' => 1,
85 'disable' => 0,
86 'uninstall' => 0,
87 ));
88 $this->assertModuleActiveByName(TRUE, 'moduletest');
89 $this->assertModuleActiveByKey(TRUE, 'test.extension.manager.moduletest');
90
91 $manager->disable(array('test.extension.manager.moduletest'));
92 $this->assertHookCounts('moduletest', array(
93 'install' => 1,
94 'enable' => 1,
95 'disable' => 1,
96 'uninstall' => 0,
97 ));
98 $this->assertModuleActiveByName(FALSE, 'moduletest');
99 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.moduletest');
100
101 $manager->enable(array('test.extension.manager.moduletest'));
102 $this->assertHookCounts('moduletest', array(
103 'install' => 1,
104 'enable' => 2,
105 'disable' => 1,
106 'uninstall' => 0,
107 ));
108 $this->assertModuleActiveByName(TRUE, 'moduletest');
109 $this->assertModuleActiveByKey(TRUE, 'test.extension.manager.moduletest');
110 }
111
112 /**
113 * Install an extension then forcibly remove the code and cleanup DB afterwards.
114 */
115 public function testInstall_DirtyRemove_Disable_Uninstall() {
116 // create temporary extension (which can dirtily remove later)
117 $this->_createExtension('test.extension.manager.module.auto1', 'module', 'test_extension_manager_module_auto1');
118 $mainfile = $this->basedir . '/test.extension.manager.module.auto1/test_extension_manager_module_auto1.php';
119 $this->assertTrue(file_exists($mainfile));
120 $manager = $this->system->getManager();
121 $this->assertModuleActiveByName(FALSE, 'test_extension_manager_module_auto1');
122 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.module.auto1');
123
124 // install it
125 $manager->install(array('test.extension.manager.module.auto1'));
126 $this->assertEquals('installed', $manager->getStatus('test.extension.manager.module.auto1'));
127 $this->assertHookCounts('test_extension_manager_module_auto1', array(
128 'install' => 1,
129 'enable' => 1,
130 'disable' => 0,
131 'uninstall' => 0,
132 ));
133 $this->assertModuleActiveByName(TRUE, 'test_extension_manager_module_auto1');
134 $this->assertModuleActiveByKey(TRUE, 'test.extension.manager.module.auto1');
135
136 // dirty removal
137 CRM_Utils_File::cleanDir($this->basedir . '/test.extension.manager.module.auto1', TRUE, FALSE);
138 $manager->refresh();
139 $this->assertEquals('installed-missing', $manager->getStatus('test.extension.manager.module.auto1'));
140
141 // disable while missing
142 $manager->disable(array('test.extension.manager.module.auto1'));
143 $this->assertEquals('disabled-missing', $manager->getStatus('test.extension.manager.module.auto1'));
144 $this->assertHookCounts('test_extension_manager_module_auto1', array(
145 'install' => 1,
146 'enable' => 1,
147 'disable' => 0, // normally called -- but not for missing modules!
148 'uninstall' => 0,
149 ));
150 $this->assertModuleActiveByName(FALSE, 'test_extension_manager_module_auto1');
151 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.moduletest');
152
153 $manager->uninstall(array('test.extension.manager.module.auto1'));
154 $this->assertHookCounts('test_extension_manager_module_auto1', array(
155 'install' => 1,
156 'enable' => 1,
157 'disable' => 0, // normally called -- but not for missing modules!
158 'uninstall' => 0, // normally called -- but not for missing modules!
159 ));
160 $this->assertEquals('unknown', $manager->getStatus('test.extension.manager.module.auto1'));
161 $this->assertModuleActiveByName(FALSE, 'test_extension_manager_module_auto1');
162 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.module.auto1');
163 }
164
165 /**
166 * Install an extension then forcibly remove the code and cleanup DB afterwards.
167 */
168 public function testInstall_DirtyRemove_Disable_Restore() {
169 // create temporary extension (which can dirtily remove later)
170 $this->_createExtension('test.extension.manager.module.auto2', 'module', 'test_extension_manager_module_auto2');
171 $mainfile = $this->basedir . '/test.extension.manager.module.auto2/test_extension_manager_module_auto2.php';
172 $this->assertTrue(file_exists($mainfile));
173 $manager = $this->system->getManager();
174 $this->assertModuleActiveByName(FALSE, 'test_extension_manager_module_auto2');
175 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.module.auto2');
176
177 // install it
178 $manager->install(array('test.extension.manager.module.auto2'));
179 $this->assertEquals('installed', $manager->getStatus('test.extension.manager.module.auto2'));
180 $this->assertHookCounts('test_extension_manager_module_auto2', array(
181 'install' => 1,
182 'enable' => 1,
183 'disable' => 0,
184 'uninstall' => 0,
185 ));
186 $this->assertModuleActiveByName(TRUE, 'test_extension_manager_module_auto2');
187 $this->assertModuleActiveByKey(TRUE, 'test.extension.manager.module.auto2');
188
189 // dirty removal
190 CRM_Utils_File::cleanDir($this->basedir . '/test.extension.manager.module.auto2', TRUE, FALSE);
191 $manager->refresh();
192 $this->assertEquals('installed-missing', $manager->getStatus('test.extension.manager.module.auto2'));
193
194 // disable while missing
195 $manager->disable(array('test.extension.manager.module.auto2'));
196 $this->assertEquals('disabled-missing', $manager->getStatus('test.extension.manager.module.auto2'));
197 $this->assertHookCounts('test_extension_manager_module_auto2', array(
198 'install' => 1,
199 'enable' => 1,
200 'disable' => 0, // normally called -- but not for missing modules!
201 'uninstall' => 0,
202 ));
203 $this->assertModuleActiveByName(FALSE, 'test_extension_manager_module_auto2');
204 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.moduletest');
205
206 // restore the code
207 $this->_createExtension('test.extension.manager.module.auto2', 'module', 'test_extension_manager_module_auto2');
208 $manager->refresh();
209 $this->assertHookCounts('test_extension_manager_module_auto2', array(
210 'install' => 1,
211 'enable' => 1,
212 'disable' => 0,
213 'uninstall' => 0,
214 ));
215 $this->assertEquals('disabled', $manager->getStatus('test.extension.manager.module.auto2'));
216 $this->assertModuleActiveByName(FALSE, 'test_extension_manager_module_auto2');
217 $this->assertModuleActiveByKey(FALSE, 'test.extension.manager.module.auto2');
218 }
219
220 /**
221 * @param $module
222 * @param array $counts expected hook invocation counts ($hookName => $count)
223 */
224 public function assertHookCounts($module, $counts) {
225 global $_test_extension_manager_moduletest_counts;
226 foreach ($counts as $key => $expected) {
227 $actual = @$_test_extension_manager_moduletest_counts[$module][$key];
228 $this->assertEquals($expected, $actual,
229 sprintf('Expected %d call(s) to hook_civicrm_%s -- found %d', $expected, $key, $actual)
230 );
231 }
232 }
233
234 /**
235 * @param $expectedIsActive
236 * @param $prefix
237 */
238 public function assertModuleActiveByName($expectedIsActive, $prefix) {
239 $activeModules = CRM_Core_PseudoConstant::getModuleExtensions(TRUE); // FIXME
240 foreach ($activeModules as $activeModule) {
241 if ($activeModule['prefix'] == $prefix) {
242 $this->assertEquals($expectedIsActive, TRUE);
243 return;
244 }
245 }
246 $this->assertEquals($expectedIsActive, FALSE);
247 }
248
249 /**
250 * @param $expectedIsActive
251 * @param $key
252 */
253 public function assertModuleActiveByKey($expectedIsActive, $key) {
254 foreach (CRM_Core_Module::getAll() as $module) {
255 if ($module->name == $key) {
256 $this->assertEquals((bool)$expectedIsActive, (bool)$module->is_active);
257 return;
258 }
259 }
260 $this->assertEquals($expectedIsActive, FALSE);
261 }
262
263 /**
264 * @param $key
265 * @param $type
266 * @param $file
267 * @param string $template
268 */
269 public function _createExtension($key, $type, $file, $template = self::MODULE_TEMPLATE) {
270 $basedir = $this->basedir;
271 mkdir("$basedir/$key");
272 file_put_contents("$basedir/$key/info.xml", "<extension key='$key' type='$type'><file>$file</file></extension>");
273 file_put_contents("$basedir/$key/$file.php", strtr($template, array('_FILE_' => $file)));
274 $this->system->getCache()->flush();
275 $this->system->getManager()->refresh();
276 }
277
278 /**
279 * @param $module
280 * @param string $name
281 */
282 public static function incHookCount($module, $name) {
283 global $_test_extension_manager_moduletest_counts;
284 $_test_extension_manager_moduletest_counts[$module][$name] = 1 + (int) $_test_extension_manager_moduletest_counts[$module][$name];
285 }
286
287 const MODULE_TEMPLATE = "
288 <?php
289 function _FILE__civicrm_install() {
290 CRM_Extension_Manager_ModuleTest::incHookCount('_FILE_', 'install');
291 }
292
293 function _FILE__civicrm_postInstall() {
294 CRM_Extension_Manager_ModuleTest::incHookCount('_FILE_', 'postInstall');
295 }
296
297 function _FILE__civicrm_uninstall() {
298 CRM_Extension_Manager_ModuleTest::incHookCount('_FILE_', 'uninstall');
299 }
300
301 function _FILE__civicrm_enable() {
302 CRM_Extension_Manager_ModuleTest::incHookCount('_FILE_', 'enable');
303 }
304
305 function _FILE__civicrm_disable() {
306 CRM_Extension_Manager_ModuleTest::incHookCount('_FILE_', 'disable');
307 }
308 ";
309
310 }