PageRenderTime 51ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/unit-test/testlib/test.core.php

http://buddypress-media.googlecode.com/
PHP | 1364 lines | 901 code | 261 blank | 202 comment | 69 complexity | 07fde83c1e4e78dcede240c351ccfa72 MD5 | raw file
Possible License(s): AGPL-1.0, Apache-2.0, GPL-2.0, LGPL-2.1
  1. <?php
  2. /**
  3. * BP-MEDIA UNIT TEST SCRIPT
  4. * Runs a user-configurable panel of unit tests against a BP-Media installation
  5. *
  6. * @version 0.1.9
  7. * @since 0.1.9
  8. * @author based on code from http://svn.automattic.com/wordpress-tests/
  9. * @package BP-Media
  10. * @subpackage Unit Test
  11. * @license GPL v2.0
  12. * @link http://code.google.com/p/buddypress-media/
  13. *
  14. * ========================================================================================================
  15. */
  16. class BPM_test_core {
  17. var $expert_mode = false; // Set true to disable all script safety interlocks
  18. var $db_name = "bpm_test"; // Name of database to connect to. Will be DESTROYED during testing.
  19. var $db_login = "test"; // Database login. Make sure user has their access ip set to %
  20. var $db_pass = "test"; // Database password
  21. var $db_host = "localhost"; // Database host
  22. var $db_prefix = "wp_"; // Prefix used in front of all database tables
  23. var $mode_wp = "single"; // Mode to run WordPress install in: "single" or "network"
  24. var $path_wp; // Path to WordPress install to run tests on
  25. var $path_plugin; // Path to plugin directory within WordPress install
  26. var $path_testcase; // Path to testcase files to run
  27. var $path_data; // Path to test data files used by testcase files
  28. var $path_log; // Path to save test results file to
  29. var $os_name; // Name of operating system test script is running on
  30. var $platform; // Operating system platform: "unix" or "windows".
  31. var $error_mode; // Error logging mode
  32. var $test_groups; // Test groups to run
  33. var $cache_engine; // Array of cache engines to enable during tests
  34. var $options; // Array of "option_name"=>"string" as set at command prompt by user.
  35. // ============================================================================================================ //
  36. var $cmd_options = array(
  37. "help" => array( "required"=>false,
  38. "has_value"=>true,
  39. "short_desc"=>"Displays help. Use --help=optionname to display detailed help for a specific option.",
  40. "long_desc"=>"",
  41. "values"=>null,
  42. "example"=>""
  43. ),
  44. "platform" => array( "required"=> false,
  45. "has_value"=> true,
  46. "short_desc"=> "Forces the script to operate as if its running on the specified operating system.",
  47. "long_desc"=> "Forces the script to operate as if its running on the specified operating system,
  48. instead of auto-detecting the operating system.",
  49. "values"=> array("Linux", "Darwin", "Windows"),
  50. "default"=> '"Auto-detect"',
  51. "example"=> "--platform=Windows"
  52. ),
  53. "expertmode" => array( "required"=> false,
  54. "has_value"=> false,
  55. "short_desc"=> "Disables all of the test script's safety interlocks.",
  56. "long_desc"=> "Disables the test script's safety interlocks, allowing arbitrary databases,
  57. and any other potentially dangerous actions included in the testcase files.",
  58. "values"=> null,
  59. "default"=> '"Off"',
  60. "example"=> "--expertmode"
  61. ),
  62. "dbname" => array( "required"=> false,
  63. "has_value"=> true,
  64. "short_desc"=> "Sets the database name to a custom value. Database is DESTROYED during testing.",
  65. "long_desc"=> "Sets the database name that the test script uses to a custom value. The database
  66. set here will be DESTROYED during testing. To use this option, you must also
  67. set the '--expertmode' option.",
  68. "values"=> null,
  69. "default"=> '"bpm_test"',
  70. "example"=> "--database=my_database --expertmode"
  71. ),
  72. "dblogin" => array( "required"=> false,
  73. "has_value"=> true,
  74. "short_desc"=> "Sets the login used when connecting to the test database.",
  75. "long_desc"=> "Sets the login used when connecting to the test database. The user specified must
  76. have root access to the database, and their ip access must be set to %.",
  77. "values"=> null,
  78. "default"=> '"test"',
  79. "example"=> "--dblogin=test_user"
  80. ),
  81. "dbpass" => array( "required"=> false,
  82. "has_value"=> true,
  83. "short_desc"=> "Sets the password used when connecting to the test database.",
  84. "long_desc"=> "Sets the password used when connecting to the test database. The user specified must
  85. have root access to the database, and their ip access must be set to %.",
  86. "values"=> null,
  87. "default"=> '"test"',
  88. "example"=> "--dbpass=my_password"
  89. ),
  90. "dbhost" => array( "required"=> false,
  91. "has_value"=> true,
  92. "short_desc"=> "Sets the host used when connecting to the test database.",
  93. "long_desc"=> "Sets the host domain name or ip address used when connecting to the test database.",
  94. "values"=> null,
  95. "default"=> '"localhost"',
  96. "example"=> "--dbpass=example.com --dbpass=192.168.1.1"
  97. ),
  98. "dbprefix" => array( "required"=> false,
  99. "has_value"=> true,
  100. "short_desc"=> "Sets the prefix used in front of all database tables.",
  101. "long_desc"=> "Sets the prefix used in front of all database tables.",
  102. "values"=> null,
  103. "default"=> '"wp_"',
  104. "example"=> "--dbprefix=my-prefix_"
  105. ),
  106. "pathwp" => array( "required"=> false,
  107. "has_value"=> true,
  108. "short_desc"=> "Sets the path to the WordPress installation used during testing.",
  109. "long_desc"=> "Sets the path to the WordPress installation used during testing. It must
  110. have BuddyPress and BP-Media installed. Any other installed plugins will be
  111. disabled during testing. The script will use wp-config.php from the test
  112. folder instead of the wp install.",
  113. "values"=> null,
  114. "default"=> "WordPress install containing the plugin the unit tests are run from.",
  115. "example"=> "--pathwp=C:\\xampp\htdocs\\"
  116. ),
  117. "pathcases" => array( "required"=> false,
  118. "has_value"=> true,
  119. "short_desc"=> "Sets the folder the script loads testcase files from.",
  120. "long_desc"=> "Sets the folder the script loads testcase files from.",
  121. "values"=> null,
  122. "default"=> '"\\unit-test\\testcases\\"',
  123. "example"=> "--pathcases=C:\\xampp\htdocs\\my_custom_testcases\\"
  124. ),
  125. "pathdata" => array( "required"=> false,
  126. "has_value"=> true,
  127. "short_desc"=> "Sets the folder the script loads test data files from.",
  128. "long_desc"=> "Sets the folder the script loads test data files from.",
  129. "values"=> null,
  130. "default"=> '"\\unit-test\\testdata\\"',
  131. "example"=> "--pathdata=C:\\xampp\htdocs\\my_custom_testdata\\"
  132. ),
  133. "pathlog" => array( "required"=> false,
  134. "has_value"=> true,
  135. "short_desc"=> "Sets the path to save the error log file to.",
  136. "long_desc"=> "Sets the path to save the error log file to. This path must be writable by
  137. the web server.",
  138. "values"=> null,
  139. "default"=> '"\\unit-test\\"',
  140. "example"=> "--pathlog=C:\\xampp\htdocs\\my_log_folder\\"
  141. ),
  142. "modewp" => array( "required"=> false,
  143. "has_value"=> true,
  144. "short_desc"=> "Sets the operation mode for the test WordPress installation.",
  145. "long_desc"=> "Sets the operation mode for the test WordPress installation. Use 'single'
  146. to test on a single-blog WP install. Use 'network' to test on a multi-blog
  147. network WP install.",
  148. "values"=> array("single", "network"),
  149. "default"=> '"Network"',
  150. "example"=> "--modewp=single"
  151. ),
  152. "errors" => array( "required"=> false,
  153. "has_value"=> true,
  154. "short_desc"=> "Sets the type of PHP errors that the script tests for.",
  155. "long_desc"=> "Sets the type of PHP errors that the script tests for.",
  156. "values"=> array("single", "network"),
  157. "default"=> '"Network"',
  158. "example"=> "--modewp=single"
  159. ),
  160. "groups" => array( "required"=> false,
  161. "has_value"=> true,
  162. "short_desc"=> "Sets the groups of tests to run.",
  163. "long_desc"=> "Sets the groups of tests to run. If you specify more than one group, you must
  164. enclose them in quotes, with one space between each group name.",
  165. "values"=> array("all", "core", "system", "database", "cache", "store", "album", "media", "nav", "meta"),
  166. "default"=> '"all"',
  167. "example"=> '--groups=core --groups="system cache store album"'
  168. ),
  169. "cache" => array( "required"=> false,
  170. "has_value"=> true,
  171. "short_desc"=> "Enables or disables caching engines during testing",
  172. "long_desc"=> "Enables or disables caching engines during testing. To use multiple engines simultaneously,
  173. list them in quotes, with a space between each engine's name. APC *must be disabled* if the test runner
  174. is called by another PHP script. See class.memory.cache.php for details.",
  175. "values"=> array("all", "off", "apc", "memcache", "redis"),
  176. "default"=> '"all"',
  177. "example"=> '--cache=off --cache="apc redis"'
  178. )
  179. );
  180. var $cmd_alias = array(
  181. "h" => "help"
  182. );
  183. // ============================================================================================================ //
  184. function BPM_test_core(){
  185. define('DIR_TESTROOT', dirname( dirname(__FILE__) ) );
  186. $this->path_plugin = realpath(DIR_TESTROOT . '/../');
  187. }
  188. /**
  189. * Parses options passed at the command line
  190. *
  191. * @version 0.1.9
  192. * @since 0.1.9
  193. *
  194. * @param bool $check | set false to disable *all* query error checking.
  195. *
  196. * @return ?
  197. */
  198. public function parseOptions(){
  199. // Create full length option names
  200. // ==========================================================
  201. $long_names = array();
  202. foreach( $this->cmd_options as $key => $data){
  203. if( $data["required"] == true ){
  204. $long_names[] = $key . ":";
  205. }
  206. else {
  207. if( $data["has_value"] == true ){
  208. $long_names[] = $key . "::";
  209. }
  210. else {
  211. $long_names[] = $key;
  212. }
  213. }
  214. }
  215. unset($key, $data);
  216. // Create single-character option name aliases
  217. // ==========================================================
  218. $short_names = "";
  219. foreach( $this->cmd_alias as $key => $alias){
  220. if( $this->cmd_options[$alias]["required"] == true ){
  221. $short_names .= $key . ":";
  222. }
  223. else {
  224. if( $this->cmd_options[$alias]["has_value"] == true ){
  225. $short_names .= $key . "::";
  226. }
  227. else {
  228. $short_names .= $key;
  229. }
  230. }
  231. }
  232. // Scrape options from the command line
  233. // ==========================================================
  234. if (is_callable('getopt')) {
  235. $raw_options = getopt($short_names, $long_names);
  236. }
  237. else {
  238. // Handle get_opt() not included on PHP for Windows prior to PHP 5.3
  239. include( dirname(__FILE__) . '/testlib/bpm-getopt.php' );
  240. $raw_options = getoptParser::getopt($short_names, $long_names);
  241. }
  242. // Re-map all options to their full names
  243. // ==========================================================
  244. $this->options = array();
  245. if( count($raw_options) > 0 ){ // Prevents array_key_exists from crashing on
  246. // null $raw_options array
  247. // Scan the raw results array for any option aliases and save them
  248. // to the processed array as their full-length names
  249. foreach( $this->cmd_alias as $key => $alias){
  250. if( array_key_exists($key, $raw_options) ){
  251. $this->options[$alias] = $raw_options[$key];
  252. }
  253. }
  254. unset($key, $alias);
  255. // Scan the raw results array for any full-length option names and
  256. // save them to the processed array. If a user specifies an option
  257. // twice, using both the short and long names, the long name wins
  258. foreach( $this->cmd_options as $key => $data){
  259. if( array_key_exists($key, $raw_options) ){
  260. $this->options[$key] = $raw_options[$key];
  261. }
  262. }
  263. }
  264. // Echo back all the options the user has set
  265. // ==========================================================
  266. if( count($this->options) > 0){
  267. if( !array_key_exists('help', $this->options) ){
  268. echo "\n== USING OPTIONS ==============================================\n\n";
  269. foreach( $this->options as $key => $val){
  270. echo " $key -> $val\n";
  271. }
  272. echo "\n===============================================================\n";
  273. }
  274. }
  275. }
  276. /**
  277. * Displays help for the unit test runner
  278. *
  279. * @version 0.1.9
  280. * @since 0.1.9
  281. *
  282. * @param bool $check | set false to disable *all* query error checking.
  283. *
  284. * @return ?
  285. */
  286. public function displayHelp() {
  287. if( array_key_exists('help', $this->options) ){
  288. if($this->options['help']){
  289. echo "\nBP-Media Help\n";
  290. echo "========================================================================\n\n";
  291. echo " --" . $this->options['help'] . "\n\n";
  292. // Description
  293. // =======================================
  294. $body = $this->cmd_options[$this->options['help']]['long_desc'];
  295. // Remove any long groups of spaces and newline characters that may have been introduced
  296. // by the way our text blocks are formatted in the $cmd_options array
  297. $body = preg_replace('|\s+|', ' ', $body);
  298. $body = preg_replace('|\n+|', '', $body);
  299. $formatted = self::formatText($term_width=70, $left_pad=" ", $right_pad="", $body);
  300. echo $formatted . "\n";
  301. // Accepted Values
  302. // =======================================
  303. if( $this->cmd_options[$this->options['help']]['values'] ){
  304. echo " options:\n\n";
  305. $body = '"' . implode( '", "', $this->cmd_options[$this->options['help']]['values'] ) . '"';
  306. // Remove any long groups of spaces and newline characters that may have been introduced
  307. // by the way our text blocks are formatted in the $cmd_options array
  308. $body = preg_replace('|\s+|', ' ', $body);
  309. $body = preg_replace('|\n+|', '', $body);
  310. $formatted = self::formatText($term_width=70, $left_pad=" ", $right_pad="", $body);
  311. echo $formatted . "\n";
  312. }
  313. // Default Value
  314. // =======================================
  315. echo " default value:\n\n";
  316. $body = $this->cmd_options[$this->options['help']]['default'];
  317. $body = preg_replace('|\s+|', ' ', $body);
  318. $body = preg_replace('|\n+|', '', $body);
  319. $formatted = self::formatText($term_width=70, $left_pad=" ", $right_pad="", $body);
  320. echo $formatted . "\n";
  321. // Example
  322. // =======================================
  323. echo " example:\n\n";
  324. $body = $this->cmd_options[$this->options['help']]['example'];
  325. $body = preg_replace('|\s+|', ' ', $body);
  326. $body = preg_replace('|\n+|', '', $body);
  327. $formatted = self::formatText($term_width=70, $left_pad=" ", $right_pad="", $body);
  328. echo $formatted . "\n";
  329. echo "========================================================================\n";
  330. }
  331. else {
  332. echo "\nBP-Media Help\n";
  333. echo "========================================================================\n\n";
  334. foreach( $this->cmd_options as $option => $data){
  335. echo " --" . $option . "\n";
  336. $body = $data['short_desc'];
  337. $body = preg_replace('|\s+|', ' ', $body);
  338. $body = preg_replace('|\n+|', '', $body);
  339. $formatted = self::formatText($term_width=70, $left_pad=" ", $right_pad="", $body);
  340. echo $formatted . "\n";
  341. }
  342. echo "========================================================================\n";
  343. }
  344. die;
  345. }
  346. }
  347. /**
  348. * Formats a text string for printing in the terminal window
  349. *
  350. * @version 0.1.9
  351. * @since 0.1.9
  352. *
  353. * @param int $term_width | Total width of the terminal window (typically 80 columns)
  354. * @param string $left_pad | Character string to pad start of each line with
  355. * @param string $right_pad | Character string to pad end of each line with
  356. * @param string $text | Text string to process
  357. *
  358. * @return string $result | Formatted text
  359. */
  360. public function formatText($term_width, $left_pad, $right_pad, $text) {
  361. // In most situations, the PHP wordwrap() function is sufficient for this
  362. // job @link http://php.net/manual/en/function.wordwrap.php but it doesn't
  363. // indent text
  364. if( strlen($text) == 0 ){
  365. return null;
  366. }
  367. // The printable line width is the terminal width minus the width of the
  368. // padding strings
  369. $max_line_width = $term_width - ( strlen($left_pad) + strlen($right_pad) );
  370. $raw_words = explode(" ", $text);
  371. $words = array();
  372. // Handle "words" that are longer than $max_line_width (this can happen
  373. // when printing file path strings)
  374. foreach($raw_words as $check_word){
  375. if( strlen($check_word) <= $max_line_width ){
  376. $words[] = $check_word;
  377. }
  378. else {
  379. $word_split = str_split($check_word, $max_line_width);
  380. $words = array_merge($words, $word_split);
  381. unset($word_split);
  382. }
  383. }
  384. unset($check_word);
  385. $total_words = count($words) - 1;
  386. $current_word = 0;
  387. // Fill a line with words until the current length + the length of the next word
  388. // in the array would exceed the max line width, then drop down to the next line
  389. while( $current_word <= $total_words ){
  390. $current_width = 0;
  391. $current_line = "";
  392. while( ($current_width <= $max_line_width) && ($current_word <= $total_words) ){
  393. if( ( strlen($words[$current_word]) + $current_width) > $max_line_width ){
  394. break;
  395. }
  396. else{
  397. $current_line .= $words[$current_word] . " ";
  398. $current_width += strlen($words[$current_word]) + 1;
  399. $current_word++;
  400. }
  401. }
  402. $result .= $left_pad . $current_line;
  403. // When jumping down to a new line, pad the end of the line with spaces
  404. // so the $right_pad characters on each line align with each other
  405. $align_spaces = $max_line_width - $current_width;
  406. for($i=0; $i<=$align_spaces; $i++){
  407. $result .= " ";
  408. }
  409. $result .= $right_pad . "\n";
  410. }
  411. return $result;
  412. }
  413. /**
  414. * Sets the credentials used to access the database
  415. *
  416. * @version 0.1.9
  417. * @since 0.1.9
  418. *
  419. * @param bool $check | set false to disable *all* query error checking.
  420. *
  421. * @return ?
  422. */
  423. public function setDatabase() {
  424. // Custom database name
  425. if( array_key_exists('dbname', $this->options) ){
  426. if( !array_key_exists('expertmode', $this->options) ){
  427. echo "\nDATABASE SAFETY INTERLOCK TRIGGERED";
  428. echo "\n##############################################################################\n";
  429. echo "\nYou set the database name to be '" . $this->options['dbname'] . "' when you ran the BP-Media";
  430. echo "\nunit test program. This database will be DESTROYED during the testing ";
  431. echo "\nprocess. If you're sure that's what you want to do, run the test ";
  432. echo "\nprogram with the option --expertmode to disable this interlock.\n";
  433. echo "\n##############################################################################\n\n";
  434. die;
  435. }
  436. else {
  437. $this->db_name = $this->options['db_name'];
  438. }
  439. }
  440. // Custom database login
  441. if( array_key_exists('dblogin', $this->options) ){
  442. $this->db_login = $this->options['dblogin'];
  443. }
  444. // Custom database pass
  445. if( array_key_exists('dbpass', $this->options) ){
  446. $this->db_pass = $this->options['dbpass'];
  447. }
  448. // Custom database host
  449. if( array_key_exists('dbhost', $this->options) ){
  450. $this->db_host = $this->options['dbhost'];
  451. }
  452. // Custom table prefix
  453. if( array_key_exists('dbprefix', $this->options) ){
  454. $this->db_prefix = $this->options['dbprefix'];
  455. }
  456. }
  457. /**
  458. * Sets the operating system platform the script runs on
  459. *
  460. * @version 0.1.9
  461. * @since 0.1.9
  462. *
  463. * @param bool $check | set false to disable *all* query error checking.
  464. *
  465. * @return ?
  466. */
  467. public function setPlatform() {
  468. // Determine operating system family
  469. // =================================================================
  470. if( array_key_exists('platform', $this->options) ){
  471. $platfrom_name = $options['platform'];
  472. }
  473. else {
  474. $platfrom_name = PHP_OS;
  475. }
  476. $unix_os_names = array(
  477. "Darwin", "Linux", "Unix", "Ubuntu", "FreeBSD", "IRIX64", "SunOS", "AIX", "Minix", "DragonFly"
  478. );
  479. if( array_search($platform_name, $unix_os_names) !== false ){
  480. $this->platform = "unix";
  481. }
  482. else {
  483. $this->platform = "windows";
  484. }
  485. }
  486. /**
  487. * Sets the path the script loads test cases from
  488. *
  489. * @version 0.1.9
  490. * @since 0.1.9
  491. *
  492. * @param bool $check | set false to disable *all* query error checking.
  493. *
  494. * @return ?
  495. */
  496. public function setPathTests() {
  497. if( array_key_exists('pathcases', $this->options) ){
  498. $this->path_testcase = $this->options['pathcases'];
  499. }
  500. else {
  501. $this->path_testcase = DIR_TESTROOT . '/testcase';
  502. define('DIR_TESTCASE', DIR_TESTROOT . '/testcase');
  503. }
  504. }
  505. /**
  506. * Sets the path the script loads test data from
  507. *
  508. * @version 0.1.9
  509. * @since 0.1.9
  510. *
  511. * @param bool $check | set false to disable *all* query error checking.
  512. *
  513. * @return ?
  514. */
  515. public function setPathData() {
  516. if( array_key_exists('pathtestdata', $this->options) ){
  517. define('DIR_TESTDATA', $this->options['pathtestdata']);
  518. }
  519. else {
  520. define('DIR_TESTDATA', DIR_TESTROOT . '/testdata');
  521. }
  522. }
  523. /**
  524. * Sets the version of WordPress that the script tests on
  525. *
  526. * @version 0.1.9
  527. * @since 0.1.9
  528. *
  529. * @param bool $check | set false to disable *all* query error checking.
  530. *
  531. * @return ?
  532. */
  533. public function setModeWP() {
  534. if( array_key_exists('modewp', $this->options) ){
  535. if($this->options['modewp'] == 'network'){
  536. define('TEST_WP', true);
  537. $this->mode_wp = 'network';
  538. }
  539. else {
  540. define('TEST_WP', true);
  541. $this->mode_wp = 'single';
  542. }
  543. }
  544. else {
  545. define('TEST_WP', true);
  546. $this->mode_wp = 'single';
  547. }
  548. }
  549. /**
  550. * Sets the path to the WordPress install the script runs on
  551. *
  552. * @version 0.1.9
  553. * @since 0.1.9
  554. *
  555. * @param bool $check | set false to disable *all* query error checking.
  556. *
  557. * @return ?
  558. */
  559. public function setPathWP() {
  560. if (!empty($opts['r'])){
  561. define('DIR_WP', realpath($opts['r']));
  562. }
  563. else {
  564. if (!empty($opts['v'])){
  565. define('DIR_WP', DIR_TESTROOT.'/wordpress-'.$opts['v']);
  566. }
  567. else {
  568. define('DIR_WP', DIR_TESTROOT.'/../../../../');
  569. }
  570. }
  571. define('ABSPATH', realpath(DIR_WP).'/');
  572. }
  573. /**
  574. * Sets the error reporting mode
  575. *
  576. * @version 0.1.9
  577. * @since 0.1.9
  578. *
  579. * @param bool $check | set false to disable *all* query error checking.
  580. *
  581. * @return ?
  582. */
  583. public function setErrorMode() {
  584. error_reporting(E_ALL & ~E_DEPRECATED); // Make sure all errors are displayed
  585. ini_set('display_errors', true);
  586. }
  587. /**
  588. * Loads the test platform libraries
  589. *
  590. * @version 0.1.9
  591. * @since 0.1.9
  592. *
  593. * @param bool $check | set false to disable *all* query error checking.
  594. *
  595. * @return ?
  596. */
  597. public function loadTestPlatform() {
  598. echo "\nRUNNING TESTS FROM: ";
  599. echo $this->path_plugin . "/\n";
  600. echo "\nLoading PHPUnit Portable...";
  601. require_once(DIR_TESTROOT . '/phpunit-portable/Autoload.php');
  602. require_once(DIR_TESTROOT . '/phpunit-portable/Util/ErrorHandler.php');
  603. $prv = new PHPUnit_Runner_Version();
  604. $phpunit_ver = $prv->id();
  605. echo " OK - Version: '$phpunit_ver'\n";
  606. require_once(DIR_TESTROOT . '/testlib/bpm-base-class.php');
  607. require_once(DIR_TESTROOT . '/testlib/bpm-utils.php');
  608. require_once(DIR_TESTROOT . '/testlib/bpm-test-db.php');
  609. require_once(DIR_TESTROOT . '/testlib/bpm-data-loader.php');
  610. require_once(DIR_TESTROOT . '/testlib/bpm-mock-mailer.php');
  611. require_once(DIR_TESTROOT . '/testlib/bpm-remap-directory.php');
  612. }
  613. /**
  614. * Sets up global constants and variables used by WordPress
  615. *
  616. * @version 0.1.9
  617. * @since 0.1.9
  618. *
  619. * @param bool $check | set false to disable *all* query error checking.
  620. *
  621. * @return ?
  622. */
  623. public function setupGlobals() {
  624. define('DB_NAME', $this->db_name);
  625. define('DB_USER', $this->db_login);
  626. define('DB_PASSWORD', $this->db_pass);
  627. define('DB_HOST', $this->db_host);
  628. define('DB_CHARSET', 'utf8');
  629. define('DB_COLLATE', '');
  630. define('AUTH_KEY', 'ug|O,+Tnh-p+(dd0w:,=mOYtesp[a3:8IevPA/fxp$)q02[ttMN2Q=P-M4OB}W@J');
  631. define('SECURE_AUTH_KEY', '*PJy_vCaQ(wE&1[z3B|O0+%_G#V-qyl%iJ0a,gjZPgo9ndM2M?;I2nk[?;b+/P|I');
  632. define('LOGGED_IN_KEY', '?t%o+ @l41.3FCOYBV|]O`_pIM@K}q-f;|bvJfB95;Do}0.o*IUPOK04@DB,f&nJ');
  633. define('NONCE_KEY', 'P_vG_Bn<GR?NM]Xy0 qME,a38pA1?b|RF,Rh+~uY Nn/&/3^$GRI|.Jqw0<xC.sS');
  634. define('AUTH_SALT', 'pJ(EvMRv9 kNn|,Ox,*eOq`N3DsIv8l*!A_ciI7h[[7E${~n/feBk/iBfImXC-BB');
  635. define('SECURE_AUTH_SALT', 'QHXYK$hI4X}7)M4@W#KHE+T+VsoNCA!d&h*GddH|ESh+Ot-{<l?V=E,]KL#j-Ym,');
  636. define('LOGGED_IN_SALT', '3Ud>[wqQp$s:tKwA6(gJrb}^H;k-SO%-DZ`WeP:IJ,[ mz$M%k#yjG-40wt mQ[,');
  637. define('NONCE_SALT', 'QR!Wk0dL[%qLxK-hB$ude%7I5We=%XwZT|+4|NHw+kDCi+u;o+^T`N+hC4)d*EQ9');
  638. global $table_prefix;
  639. $table_prefix = $this->db_prefix;
  640. define('WPLANG', '');
  641. define('WP_DEBUG', false);
  642. }
  643. /**
  644. * Sets up the database
  645. *
  646. * @version 0.1.9
  647. * @since 0.1.9
  648. *
  649. * @param bool $check | set false to disable *all* query error checking.
  650. *
  651. * @return ?
  652. */
  653. public function setupDB() {
  654. // Connect to the SQL server
  655. // =================================================================
  656. echo "Connecting to SQL server...";
  657. $bpm_db = new BPM_test_db(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST );
  658. // Trap db user not existing on the SQL server, or not being allowed to
  659. // connect from localhost
  660. if(!$bpm_db->dbh){
  661. $dbhost = DB_HOST;
  662. $dbuser = DB_USER;
  663. $dbpassword = DB_PASSWORD;
  664. $dbname = DB_NAME;
  665. $error = " FAIL\n\n";
  666. $error .= "Couldn't establish a SQL server connection\n\n";
  667. $error .= "Host: $dbhost\n";
  668. $error .= "Database: $dbname\n";
  669. $error .= "User: $dbuser\n";
  670. $error .= "Pass: $dbpassword\n\n";
  671. $error .= "1) Check that the database '$dbname' exists on the server.\n";
  672. $error .= "2) Check that user '$dbuser' with password '$dbpassword' has ALL PRIVLEGES on '$dbname'\n";
  673. $error .= "3) Set user '$dbuser''s allowed login IP to 'localhost' ('%' does not always work)\n\n";
  674. echo $error; die;
  675. }
  676. else {
  677. echo " OK - Handle: '$bpm_db->dbh' \n";
  678. }
  679. // Open the bpm_test database
  680. // =================================================================
  681. echo "Checking if database can be written to...";
  682. // Trap user existing but database not existing on SQL server
  683. if( !@mysql_select_db( DB_NAME, $bpm_db->dbh ) ){
  684. $dbhost = DB_HOST;
  685. $dbuser = DB_USER;
  686. $dbpassword = DB_PASSWORD;
  687. $dbname = DB_NAME;
  688. $error = " FAIL\n\n";
  689. $error .= "Couldn't open database '$dbname' on the SQL server\n\n";
  690. $error .= "Host: $dbhost\n";
  691. $error .= "Database: $dbname\n";
  692. $error .= "User: $dbuser\n";
  693. $error .= "Pass: $dbpassword\n\n";
  694. $error .= "1) Check that the database '$dbname' exists on the server.\n";
  695. $error .= "2) Check that user '$dbuser' with password '$dbpassword' has ALL PRIVLEGES on '$dbname'\n";
  696. $error .= "3) Set user '$dbuser''s allowed login IP to 'localhost' ('%' does not always work)\n\n";
  697. echo $error; die;
  698. }
  699. else {
  700. echo " OK\n";
  701. }
  702. // Clear all existing db tables
  703. // =================================================================
  704. echo "Dropping old tables...";
  705. drop_tables($bpm_db);
  706. echo " OK\n";
  707. // Determine the stub for the plugin's folder. If the test script is running
  708. // from "c:/xampp/htdocs/wp-content/plugins/foo_plugin/unit-test/" we want "foo_plugin"
  709. // =================================================================
  710. $stub_start = strrpos($this->path_plugin, "/");
  711. if(!$stub_start){
  712. $stub_start = strrpos($this->path_plugin, "\\");
  713. }
  714. $stub_end = strlen($this->path_plugin);
  715. $stub = substr($this->path_plugin, $stub_start + 1, $stub_end - 1);
  716. echo "Loading test db into SQL server...";
  717. load_sql_dump($bpm_db, DIR_TESTDATA.'/bpm_test_db_image.sql');
  718. echo " OK\n";
  719. // Apply directory stub mapping solution to the SQL database
  720. // (function is located in bpm-remap-directory.php and needs to be updated for each BP release)
  721. // =================================================================
  722. echo "Remapping active directory...";
  723. $remap_ok = remap_directory($bpm_db, $stub, &$error);
  724. if($remap_ok){
  725. echo " OK\n";
  726. }
  727. else {
  728. echo " FAIL\n";
  729. echo $error;
  730. die;
  731. }
  732. }
  733. /**
  734. * Sets the caching engines to use during tests. Must be run after the BPM core is loaded, because
  735. * it needs access to the global cache singleton.
  736. *
  737. * @version 0.1.9
  738. * @since 0.1.9
  739. *
  740. * @param bool $check | set false to disable *all* query error checking.
  741. *
  742. * @return ?
  743. */
  744. public function setCache() {
  745. $all_cache_engines = array("apc", "memcached", "redis");
  746. if( array_key_exists('cache', $this->options) ){
  747. // Remove beginning and end padding, reduce groups of spaces to a
  748. // single space, remove commas, convert all characters to lower case
  749. $cache = trim($this->options['cache']);
  750. $cache = preg_replace('|\s+|', ' ', $cache);
  751. $cache = preg_replace('|,+|', '', $cache);
  752. $cache = strtolower($cache);
  753. $this->cache_engine = explode(" ", $cache);
  754. // At this point, the array will contain keys for each cache
  755. // engine the user listed
  756. if( array_search( 'all', $this->cache_engine ) !== false ){
  757. // Use all available cache engines
  758. $this->cache_engine = $all_cache_engines;
  759. }
  760. elseif( array_search( 'off', $this->cache_engine ) !== false ){
  761. // Disable all cache engines
  762. $this->cache_engine = false;
  763. }
  764. }
  765. else {
  766. // Default to using all avaliable cache engines
  767. $this->cache_engine = $all_cache_engines;
  768. }
  769. // Handle APC being disabled for *just* the cli
  770. // ====================================================
  771. $apc_cli_enabled = ini_get('apc.enable_cli');
  772. if(!$apc_cli_enabled ){
  773. echo "APC has been disabled for CLI scripts. Some tests might be skipped.\n";
  774. if( is_array($this->cache_engine) ){
  775. $apc_idx = array_search( 'apc', $this->cache_engine );
  776. if($apc_idx !== false){
  777. unset($this->cache_engine[$apc_idx]);
  778. }
  779. }
  780. }
  781. }
  782. /**
  783. * Sets the operating system platform the script runs on
  784. *
  785. * @version 0.1.9
  786. * @since 0.1.9
  787. *
  788. * @param bool $check | set false to disable *all* query error checking.
  789. *
  790. * @return ?
  791. */
  792. public function runTests() {
  793. // Run the unit tests
  794. // ########################################################################################
  795. echo "\n";
  796. define('PHPUnit_MAIN_METHOD', false);
  797. // Load all the test files as set in config.php
  798. // =================================================================
  799. if( PHP_OS == "Darwin"){
  800. require_once($this->path_testcase . '/dictionary.php');
  801. }
  802. else {
  803. require_once($this->path_testcase . '/dictionary.php'); // Note the './'
  804. }
  805. $cls = new BPM_test_dictionary();
  806. $cls->getMockClasses();
  807. // Set test groups
  808. // ====================================================
  809. $all_test_groups = array('core', 'system', 'database', 'apc_cache', 'disk_cache',
  810. 'store', 'album', 'media', 'nav', 'meta', 'rbac');
  811. if( array_key_exists('groups', $this->options) ){
  812. // Remove beginning and end padding, reduce groups of spaces to a
  813. // single space, remove commas, convert all characters to lower case
  814. $groups = trim($this->options['groups']);
  815. $groups = preg_replace('|\s+|', ' ', $groups);
  816. $groups = preg_replace('|,+|', '', $groups);
  817. $groups = strtolower($groups);
  818. $this->test_groups = explode(" ", $groups);
  819. // If the user passes 'all' as the test group name, null the array
  820. // so the dictionary class runs all available tests
  821. if( array_search( 'all', $this->test_groups ) !== false ){
  822. $this->test_groups = $all_test_groups;
  823. }
  824. }
  825. else {
  826. $this->test_groups = $all_test_groups;
  827. }
  828. // Handle APC being disabled for *just* the cli
  829. // ====================================================
  830. $apc_cli_enabled = ini_get('apc.enable_cli');
  831. if(!$apc_cli_enabled ){
  832. if( is_array($this->test_groups) ){
  833. $apc_idx = array_search( 'apc_cache', $this->test_groups );
  834. if($apc_idx !== false){
  835. unset($this->test_groups[$apc_idx]);
  836. }
  837. }
  838. }
  839. $cls->getTestCases($this->test_groups);
  840. $classes = bpmtest_get_all_test_cases();
  841. if( isset($opts['l']) ) {
  842. bpmtest_listall_testcases($classes);
  843. }
  844. else {
  845. do_action('test_start');
  846. // Hide warnings during testing, since that's the normal WP behaviour
  847. if ( !WP_DEBUG ) {
  848. error_reporting(E_ALL ^ E_NOTICE);
  849. }
  850. // Run the tests and print the results
  851. $result = bpmtest_run_tests($classes, @$opts['t']);
  852. return $result;
  853. }
  854. }
  855. /**
  856. * Sets the operating system platform the script runs on
  857. *
  858. * @version 0.1.9
  859. * @since 0.1.9
  860. *
  861. * @param bool $check | set false to disable *all* query error checking.
  862. *
  863. * @return ?
  864. */
  865. public function logResults($test_result, $web_page=false) {
  866. if(!$web_page){
  867. bpmtest_print_result($test_result['printer'],$test_result['suite']);
  868. }
  869. else {
  870. $result = $test_result['suite'];
  871. $pass = $result->passed();
  872. $number_of_tests = $result->count();
  873. $detected_failures = $result->failureCount();
  874. $failures= $result->failures();
  875. $incompleted_tests= $result->notImplemented();
  876. $skipped = $result->skipped();
  877. $number_skipped=$result->skippedCount();
  878. $success = "unsuccessfully";
  879. $entire_test = $result->wasSuccessful();
  880. if($entire_test)
  881. $success = "successfully";
  882. //print_r($pass);
  883. ?>
  884. <h2>Test Results</h2>
  885. <p>The test suite finished <?php echo $success ?>.<br/>
  886. In <?php echo $number_of_tests?> tests there was
  887. <?php echo $number_skipped?> skiped, <?php echo count($incompleted_tests);?> incomplete,
  888. <?php echo $detected_failures?> failing and <?php echo count($pass) ?> passed!</p>
  889. <table class="widefat fixed" cellspacing="0">
  890. <thead>
  891. <tr>
  892. <th id="test" class="manage-column" scope="col">Test Case</th>
  893. <th id="function" class="manage-column" scope="col">Test</th>
  894. <th id="status" class="manage-column" scope="col">Status</th>
  895. <th id="Message" class="manage-column" scope="col">Message</th>
  896. </tr>
  897. </thead>
  898. <tfoot>
  899. <tr>
  900. <th id="test" class="manage-column" scope="col">Test Case</th>
  901. <th id="function" class="manage-column" scope="col">Test</th>
  902. <th id="status" class="manage-column" scope="col">Status</th>
  903. <th id="Message" class="manage-column" scope="col">Message</th>
  904. </tr>
  905. </tfoot>
  906. <tbody>
  907. <?php
  908. $passedKeys = array_keys($pass);
  909. $skippedKeys = array_keys($skipped);
  910. $incompletedKeys = array_keys($incompleted_tests);
  911. self::arrange_results($skippedKeys,'skipped');
  912. self::arrange_results($incompletedKeys,'incompleted');
  913. self::arrange_results($failuresKeys,'failed');
  914. self::arrange_results($passedKeys,'passed');
  915. //handle failures
  916. foreach ($failures as $failure)
  917. {
  918. if($failure instanceof PHPUnit_Framework_TestFailure)
  919. {
  920. $failure_msg = $failure->getExceptionAsString();
  921. $failedTest = $failure->failedTest();
  922. if ($failedTest instanceof PHPUnit_Framework_SelfDescribing)
  923. $testName = $failedTest->toString();
  924. else
  925. $testName = get_class($failedTest);
  926. $var = explode('::',$testName);
  927. $testname=$var[0];
  928. $function=$var[1];
  929. echo
  930. '<tr class="alternate author-self status-publish iedit" valign="top">
  931. <td class="test-title column-title">
  932. <strong>'.$testname.'</strong>
  933. </td>
  934. <td class="function column-status">
  935. <strong>'.$function.'</strong>
  936. </td>
  937. <td class="status column-status">
  938. <strong>failed</strong>
  939. </td>
  940. <td class="message column-status">
  941. <strong>'.$failure_msg.'</strong>
  942. </td>';
  943. }
  944. }
  945. ?>
  946. </tbody>
  947. </table>
  948. <?php
  949. }
  950. }
  951. function arrange_results($array,$status){
  952. if(!empty($array))
  953. {
  954. foreach ($array as $test)
  955. {
  956. $var = explode('::',$test);
  957. $testname=$var[0];
  958. $function=$var[1];
  959. self::print_row($testname,$function,$status);
  960. }
  961. }
  962. }
  963. function print_row($test, $function,$status)
  964. {
  965. echo
  966. '<tr class="alternate author-self status-publish iedit" valign="top">
  967. <td class="test-title column-title">
  968. <strong>'.$test.'</strong>
  969. </td>
  970. <td class="function column-status">
  971. <strong>'.$function.'</strong>
  972. </td>
  973. <td class="status column-status">
  974. <strong>'.$status.'</strong>
  975. </td>
  976. <td class="message column-status">
  977. <strong></strong>
  978. </td>';
  979. }
  980. }
  981. ?>