]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/SugarTestHelper.php
Release 6.5.1
[Github/sugarcrm.git] / tests / SugarTestHelper.php
1 <?php
2 /*********************************************************************************
3  * SugarCRM Community Edition is a customer relationship management program developed by
4  * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
5  * 
6  * This program is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License version 3 as published by the
8  * Free Software Foundation with the addition of the following permission added
9  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12  * 
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
16  * details.
17  * 
18  * You should have received a copy of the GNU Affero General Public License along with
19  * this program; if not, see http://www.gnu.org/licenses or write to the Free
20  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301 USA.
22  * 
23  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
25  * 
26  * The interactive user interfaces in modified source and object code versions
27  * of this program must display Appropriate Legal Notices, as required under
28  * Section 5 of the GNU Affero General Public License version 3.
29  * 
30  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31  * these Appropriate Legal Notices must retain the display of the "Powered by
32  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33  * technical reasons, the Appropriate Legal Notices must display the words
34  * "Powered by SugarCRM".
35  ********************************************************************************/
36
37
38 if(!defined('sugarEntry')) define('sugarEntry', true);
39
40 set_include_path(
41     dirname(__FILE__) . PATH_SEPARATOR .
42     dirname(__FILE__) . '/..' . PATH_SEPARATOR .
43     get_include_path()
44 );
45
46 // constant to indicate that we are running tests
47 if (!defined('SUGAR_PHPUNIT_RUNNER'))
48     define('SUGAR_PHPUNIT_RUNNER', true);
49
50 // initialize the various globals we use
51 global $sugar_config, $db, $fileName, $current_user, $locale, $current_language;
52
53 if ( !isset($_SERVER['HTTP_USER_AGENT']) )
54     // we are probably running tests from the command line
55     $_SERVER['HTTP_USER_AGENT'] = 'cli';
56
57 // move current working directory
58 chdir(dirname(__FILE__) . '/..');
59
60 require_once('include/entryPoint.php');
61
62 require_once('include/utils/layout_utils.php');
63
64 $GLOBALS['db'] = DBManagerFactory::getInstance();
65
66 $current_language = $sugar_config['default_language'];
67 // disable the SugarLogger
68 $sugar_config['logger']['level'] = 'fatal';
69
70 $GLOBALS['sugar_config']['default_permissions'] = array (
71                 'dir_mode' => 02770,
72                 'file_mode' => 0777,
73                 'chown' => '',
74                 'chgrp' => '',
75         );
76
77 $GLOBALS['js_version_key'] = 'testrunner';
78
79 if ( !isset($_SERVER['SERVER_SOFTWARE']) )
80     $_SERVER["SERVER_SOFTWARE"] = 'PHPUnit';
81
82 // helps silence the license checking when running unit tests.
83 $_SESSION['VALIDATION_EXPIRES_IN'] = 'valid';
84
85 $GLOBALS['startTime'] = microtime(true);
86
87 // clean out the cache directory
88 require_once('modules/Administration/QuickRepairAndRebuild.php');
89 $repair = new RepairAndClear();
90 $repair->module_list = array();
91 $repair->show_output = false;
92 $repair->clearJsLangFiles();
93 $repair->clearJsFiles();
94
95 // mark that we got by the admin wizard already
96 $focus = new Administration();
97 $focus->retrieveSettings();
98 $focus->saveSetting('system','adminwizard',1);
99
100 // include the other test tools
101 require_once 'SugarTestObjectUtilities.php';
102 require_once 'SugarTestProjectUtilities.php';
103 require_once 'SugarTestProjectTaskUtilities.php';
104 require_once 'SugarTestUserUtilities.php';
105 require_once 'SugarTestLangPackCreator.php';
106 require_once 'SugarTestThemeUtilities.php';
107 require_once 'SugarTestContactUtilities.php';
108 require_once 'SugarTestEmailUtilities.php';
109 require_once 'SugarTestCampaignUtilities.php';
110 require_once 'SugarTestLeadUtilities.php';
111 require_once 'SugarTestStudioUtilities.php';
112 require_once 'SugarTestMeetingUtilities.php';
113 require_once 'SugarTestCallUtilities.php';
114 require_once 'SugarTestAccountUtilities.php';
115 require_once 'SugarTestTrackerUtility.php';
116 require_once 'SugarTestImportUtilities.php';
117 require_once 'SugarTestMergeUtilities.php';
118 require_once 'SugarTestTaskUtilities.php';
119
120 $GLOBALS['db']->commit();
121
122 // define our testcase subclass
123 class Sugar_PHPUnit_Framework_TestCase extends PHPUnit_Framework_TestCase
124 {
125     protected $backupGlobals = FALSE;
126
127     protected $useOutputBuffering = true;
128
129     protected function assertPreConditions()
130     {
131         if(isset($GLOBALS['log'])) {
132             $GLOBALS['log']->info("START TEST: {$this->getName(false)}");
133         }
134         SugarCache::instance()->flush();
135     }
136
137     protected function assertPostConditions() {
138         if(!empty($_REQUEST)) {
139             foreach(array_keys($_REQUEST) as $k) {
140                         unset($_REQUEST[$k]);
141                     }
142         }
143
144         if(!empty($_POST)) {
145             foreach(array_keys($_POST) as $k) {
146                         unset($_POST[$k]);
147                     }
148         }
149
150         if(!empty($_GET)) {
151             foreach(array_keys($_GET) as $k) {
152                         unset($_GET[$k]);
153                     }
154         }
155         if(isset($GLOBALS['log'])) {
156             $GLOBALS['log']->info("DONE TEST: {$this->getName(false)}");
157         }
158         // reset error handler in case somebody set it
159         restore_error_handler();
160     }
161
162     public static function tearDownAfterClass()
163     {
164         unset($GLOBALS['disable_date_format']);
165         unset($GLOBALS['saving_relationships']);
166         unset($GLOBALS['updating_relationships']);
167         $GLOBALS['timedate']->clearCache();
168     }
169 }
170
171 // define output testcase subclass
172 class Sugar_PHPUnit_Framework_OutputTestCase extends PHPUnit_Extensions_OutputTestCase
173 {
174     protected $backupGlobals = FALSE;
175
176     protected $_notRegex;
177     protected $_outputCheck;
178
179     protected function assertPreConditions()
180     {
181         if(isset($GLOBALS['log'])) {
182             $GLOBALS['log']->info("START TEST: {$this->getName(false)}");
183         }
184         SugarCache::instance()->flush();
185     }
186
187     protected function assertPostConditions() {
188         if(!empty($_REQUEST)) {
189             foreach(array_keys($_REQUEST) as $k) {
190                         unset($_REQUEST[$k]);
191                     }
192         }
193
194         if(!empty($_POST)) {
195             foreach(array_keys($_POST) as $k) {
196                         unset($_POST[$k]);
197                     }
198         }
199
200         if(!empty($_GET)) {
201             foreach(array_keys($_GET) as $k) {
202                         unset($_GET[$k]);
203                     }
204         }
205         if(isset($GLOBALS['log'])) {
206             $GLOBALS['log']->info("DONE TEST: {$this->getName(false)}");
207         }
208     }
209
210     protected function NotRegexCallback($output)
211     {
212         if(empty($this->_notRegex)) {
213             return true;
214         }
215         $this->assertNotRegExp($this->_notRegex, $output);
216         return true;
217     }
218
219     public function setOutputCheck($callback)
220     {
221         if (!is_callable($callback)) {
222             throw new PHPUnit_Framework_Exception;
223         }
224
225         $this->_outputCheck = $callback;
226     }
227
228     protected function runTest()
229     {
230                 $testResult = parent::runTest();
231         if($this->_outputCheck) {
232             $this->assertTrue(call_user_func($this->_outputCheck, $this->output));
233         }
234         return $testResult;
235     }
236
237     public function expectOutputNotRegex($expectedRegex)
238     {
239         if (is_string($expectedRegex) || is_null($expectedRegex)) {
240             $this->_notRegex = $expectedRegex;
241         }
242
243         $this->setOutputCheck(array($this, "NotRegexCallback"));
244     }
245
246 }
247
248 // define a mock logger interface; used for capturing logging messages emited
249 // the test suite
250 class SugarMockLogger
251 {
252         private $_messages = array();
253
254         public function __call($method, $message)
255         {
256                 $this->messages[] = strtoupper($method) . ': ' . $message[0];
257         }
258
259         public function getLastMessage()
260         {
261                 return end($this->messages);
262         }
263
264         public function getMessageCount()
265         {
266                 return count($this->messages);
267         }
268 }
269
270 /**
271  * Own exception for SugarTestHelper class
272  *
273  * @author mgusev@sugarcrm.com
274  */
275 class SugarTestHelperException extends PHPUnit_Framework_Exception
276 {
277
278 }
279
280 /**
281  * Helper for initialization of global variables of SugarCRM
282  *
283  * @author mgusev@sugarcrm.com
284  */
285 class SugarTestHelper
286 {
287     /**
288      * @var array array of registered vars. It allows helper to unregister them on tearDown
289      */
290     protected static $registeredVars = array();
291
292     /**
293      * @var array array of global vars. They are storing on init one time and restoring in global scope each tearDown
294      */
295     protected static $initVars = array(
296         'GLOBALS' => array()
297     );
298
299     /**
300      * @var array of system preference of SugarCRM as theme etc. They are storing on init one time and restoring each tearDown
301      */
302     protected static $systemVars = array();
303
304     /**
305      * @var bool is SugarTestHelper inited or not. Just to skip initialization on the second and others call of init method
306      */
307     protected static $isInited = false;
308
309     /**
310      * All methods are static because of it we disable constructor
311      */
312     private function __construct()
313     {
314     }
315
316     /**
317      * All methods are static because of it we disable clone
318      */
319     private function __clone()
320     {
321     }
322
323     /**
324      * Initialization of main variables of SugarCRM in global scope
325      *
326      * @static
327      */
328     public static function init()
329     {
330         if (self::$isInited == true)
331         {
332             return true;
333         }
334
335         // initialization & backup of sugar_config
336         self::$initVars['GLOBALS']['sugar_config'] = null;
337         if ($GLOBALS['sugar_config'])
338         {
339             self::$initVars['GLOBALS']['sugar_config'] = $GLOBALS['sugar_config'];
340         }
341         if (self::$initVars['GLOBALS']['sugar_config'] == false)
342         {
343             global $sugar_config;
344             if (is_file('config.php'))
345             {
346                 require_once('config.php');
347             }
348             if (is_file('config_override.php'))
349             {
350                 require_once('config_override.php');
351             }
352             self::$initVars['GLOBALS']['sugar_config'] = $GLOBALS['sugar_config'];
353         }
354
355         // backup of current_language
356         self::$initVars['GLOBALS']['current_language'] = 'en_us';
357         if (isset($sugar_config['current_language']))
358         {
359             self::$initVars['GLOBALS']['current_language'] = $sugar_config['current_language'];
360         }
361         if (isset($GLOBALS['current_language']))
362         {
363             self::$initVars['GLOBALS']['current_language'] = $GLOBALS['current_language'];
364         }
365         $GLOBALS['current_language'] = self::$initVars['GLOBALS']['current_language'];
366
367         // backup of reload_vardefs
368         self::$initVars['GLOBALS']['reload_vardefs'] = null;
369         if (isset($GLOBALS['reload_vardefs']))
370         {
371             self::$initVars['GLOBALS']['reload_vardefs'] = $GLOBALS['reload_vardefs'];
372         }
373
374         // backup of locale
375         self::$initVars['GLOBALS']['locale'] = null;
376         if (isset($GLOBALS['locale']))
377         {
378             self::$initVars['GLOBALS']['locale'] = $GLOBALS['locale'];
379         }
380         if (self::$initVars['GLOBALS']['locale'] == false)
381         {
382             self::$initVars['GLOBALS']['locale'] = new Localization();
383         }
384
385         // backup of service_object
386         self::$initVars['GLOBALS']['service_object'] = null;
387         if (isset($GLOBALS['service_object']))
388         {
389             self::$initVars['GLOBALS']['service_object'] = $GLOBALS['service_object'];
390         }
391
392         // backup of SugarThemeRegistry
393         self::$systemVars['SugarThemeRegistry'] = SugarThemeRegistry::current();
394
395         self::$isInited = true;
396     }
397
398     /**
399      * Checking is there helper for variable or not
400      *
401      * @static
402      * @param string $varName name of global variable of SugarCRM
403      * @return bool is there helper for a variable or not
404      * @throws SugarTestHelperException fired when there is no implementation of helper for a variable
405      */
406     protected static function checkHelper($varName)
407     {
408         if (method_exists(__CLASS__, 'setUp_' . $varName) == false)
409         {
410             throw new SugarTestHelperException('setUp for $' . $varName . ' is not implemented. ' . __CLASS__ . '::setUp_' . $varName);
411         }
412     }
413
414     /**
415      * Entry point for setup of global variable
416      *
417      * @static
418      * @param string $varName name of global variable of SugarCRM
419      * @param array $params some parameters for helper. For example for $mod_strings or $current_user
420      * @return bool is variable setuped or not
421      */
422     public static function setUp($varName, $params = array())
423     {
424         self::init();
425         self::checkHelper($varName);
426         return call_user_func(__CLASS__ . '::setUp_' . $varName, $params);
427     }
428
429     /**
430      * Clean up all registered variables and restore $initVars and $systemVars
431      * @static
432      * @return bool status of tearDown
433      */
434     public static function tearDown()
435     {
436         self::init();
437         foreach(self::$registeredVars as $varName => $isCalled)
438         {
439             if ($isCalled)
440             {
441                 unset(self::$registeredVars[$varName]);
442                 if (method_exists(__CLASS__, 'tearDown_' . $varName))
443                 {
444                     call_user_func(__CLASS__ . '::tearDown_' . $varName, array());
445                 }
446                 elseif (isset($GLOBALS[$varName]))
447                 {
448                     unset($GLOBALS[$varName]);
449                 }
450             }
451         }
452
453         // Restoring of system variables
454         foreach(self::$initVars as $scope => $vars)
455         {
456             foreach ($vars as $name => $value)
457             {
458                 $GLOBALS[$scope][$name] = $value;
459             }
460         }
461
462         // Restoring of theme
463         SugarThemeRegistry::set(self::$systemVars['SugarThemeRegistry']->dirName);
464
465         return true;
466     }
467
468     /**
469      * Registration of $current_user in global scope
470      *
471      * @static
472      * @param array $params parameters for SugarTestUserUtilities::createAnonymousUser method
473      * @return bool is variable setuped or not
474      */
475     protected static function setUp_current_user(array $params)
476     {
477         self::$registeredVars['current_user'] = true;
478         $GLOBALS['current_user'] = call_user_func_array('SugarTestUserUtilities::createAnonymousUser', $params);
479         return true;
480     }
481
482     /**
483      * Removal of $current_user from global scope
484      *
485      * @static
486      * @return bool is variable removed or not
487      */
488     protected static function tearDown_current_user()
489     {
490         SugarTestUserUtilities::removeAllCreatedAnonymousUsers();
491         unset($GLOBALS['current_user']);
492         return true;
493     }
494
495     /**
496      * Registration of $beanList in global scope
497      *
498      * @static
499      * @return bool is variable setuped or not
500      */
501     protected static function setUp_beanList()
502     {
503         self::$registeredVars['beanList'] = true;
504         global $beanList;
505         require('include/modules.php');
506         return true;
507     }
508
509     /**
510      * Registration of $beanFiles in global scope
511      *
512      * @static
513      * @return bool is variable setuped or not
514      */
515     protected static function setUp_beanFiles()
516     {
517         self::$registeredVars['beanFiles'] = true;
518         global $beanFiles;
519         require('include/modules.php');
520         return true;
521     }
522
523     /**
524      * Registration of $moduleList in global scope
525      *
526      * @static
527      * @return bool is variable setuped or not
528      */
529     protected static function setUp_moduleList()
530     {
531         self::$registeredVars['moduleList'] = true;
532         self::setUp_app_list_strings();
533         $GLOBALS['moduleList'] = $GLOBALS['app_list_strings']['moduleList'];
534         return true;
535     }
536
537     /**
538      * Registration of $modListHeader in global scope
539      *
540      * @static
541      * @return bool is variable setuped or not
542      */
543     protected static function setUp_modListHeader()
544     {
545         self::$registeredVars['modListHeader'] = true;
546         if (isset($GLOBALS['current_user']) == false)
547         {
548             self::setUp_current_user(array(
549                 true,
550                 1
551             ));
552         }
553         $GLOBALS['modListHeader'] = query_module_access_list($GLOBALS['current_user']);
554         return true;
555     }
556
557     /**
558      * Registration of $app_strings in global scope
559      *
560      * @static
561      * @return bool is variable setuped or not
562      */
563     protected static function setUp_app_strings()
564     {
565         self::$registeredVars['app_strings'] = true;
566         $GLOBALS['app_strings'] = return_application_language($GLOBALS['current_language']);
567         return true;
568     }
569
570     /**
571      * Registration of $app_list_strings in global scope
572      *
573      * @static
574      * @return bool is variable setuped or not
575      */
576     protected static function setUp_app_list_strings()
577     {
578         self::$registeredVars['app_list_strings'] = true;
579         $GLOBALS['app_list_strings'] = return_app_list_strings_language($GLOBALS['current_language']);
580         return true;
581     }
582
583     /**
584      * Registration of $timedate in global scope
585      *
586      * @static
587      * @return bool is variable setuped or not
588      */
589     protected static function setUp_timedate()
590     {
591         self::$registeredVars['timedate'] = true;
592         $GLOBALS['timedate'] = TimeDate::getInstance();
593         return true;
594     }
595
596     /**
597      * Removal of $timedate from global scope
598      *
599      * @static
600      * @return bool is variable removed or not
601      */
602     protected static function tearDown_timedate()
603     {
604         $GLOBALS['timedate']->clearCache();
605         return true;
606     }
607
608     /**
609      * Registration of $mod_strings in global scope
610      *
611      * @static
612      * @param array $params parameters for return_module_language function
613      * @return bool is variable setuped or not
614      */
615     protected static function setUp_mod_strings(array $params)
616     {
617         self::$registeredVars['mod_strings'] = true;
618         $GLOBALS['mod_strings'] = return_module_language($GLOBALS['current_language'], $params[0]);
619         return true;
620     }
621 }