PEAR
[ class tree: PEAR ] [ index: PEAR ] [ all elements ]

Source for file RunTest.php

Documentation is available at RunTest.php

  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 5                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 3.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at the following url:           |
  11. // | http://www.php.net/license/3_0.txt.                                  |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: Tomas V.V.Cox <cox@idecnet.com>                             |
  17. // |          Greg Beaver <cellog@php.net>                                |
  18. // |                                                                      |
  19. // +----------------------------------------------------------------------+
  20. //
  21. // $Id: RunTest.php,v 1.3.2.4 2005/02/17 17:47:55 cellog Exp $
  22. //
  23.  
  24. /**
  25.  * Simplified version of PHP's test suite
  26.  * -- EXPERIMENTAL --
  27.  
  28.  Try it with:
  29.  
  30.  $ php -r 'include "../PEAR/RunTest.php"; $t=new PEAR_RunTest; $o=$t->run("./pear_system.phpt");print_r($o);'
  31.  
  32.  
  33. TODO:
  34.  
  35. Actually finish the development and testing
  36.  
  37.  */
  38.  
  39. require_once 'PEAR.php';
  40. require_once 'PEAR/Config.php';
  41.  
  42. define('DETAILED', 1);
  43. putenv("PHP_PEAR_RUNTESTS=1");
  44.  
  45. class PEAR_RunTest
  46. {
  47.     var $_logger;
  48.  
  49.     /**
  50.      * An object that supports the PEAR_Common->log() signature, or null
  51.      * @param PEAR_Common|null
  52.      */
  53.     function PEAR_RunTest($logger = null)
  54.     {
  55.         $this->_logger = $logger;
  56.     }
  57.  
  58.     //
  59.     //  Run an individual test case.
  60.     //
  61.  
  62.     function run($file, $ini_settings = '')
  63.     {
  64.         $cwd = getcwd();
  65.         $conf = &PEAR_Config::singleton();
  66.         $php = $conf->get('php_bin');
  67.         //var_dump($php);exit;
  68.         global $log_format, $info_params, $ini_overwrites;
  69.  
  70.         $info_params = '';
  71.         $log_format = 'LEOD';
  72.  
  73.         // Load the sections of the test file.
  74.         $section_text = array(
  75.             'TEST'    => '(unnamed test)',
  76.             'SKIPIF'  => '',
  77.             'GET'     => '',
  78.             'ARGS'    => '',
  79.         );
  80.  
  81.         if (!is_file($file) || !$fp = fopen($file, "r")) {
  82.             return PEAR::raiseError("Cannot open test file: $file");
  83.         }
  84.  
  85.         $section = '';
  86.         while (!feof($fp)) {
  87.             $line = fgets($fp);
  88.  
  89.             // Match the beginning of a section.
  90.             if (ereg('^--([A-Z]+)--',$line,$r)) {
  91.                 $section = $r[1];
  92.                 $section_text[$section] = '';
  93.                 continue;
  94.             }
  95.  
  96.             // Add to the section text.
  97.             $section_text[$section] .= $line;
  98.         }
  99.         fclose($fp);
  100.  
  101.         $shortname = str_replace($cwd.'/', '', $file);
  102.         $tested = trim($section_text['TEST'])." [$shortname]";
  103.  
  104.         $tmp = realpath(dirname($file));
  105.         $tmp_skipif = $tmp . uniqid('/phpt.');
  106.         $tmp_file   = ereg_replace('\.phpt$','.php',$file);
  107.         $tmp_post   = $tmp . uniqid('/phpt.');
  108.  
  109.         @unlink($tmp_skipif);
  110.         @unlink($tmp_file);
  111.         @unlink($tmp_post);
  112.  
  113.         // unlink old test results
  114.         @unlink(ereg_replace('\.phpt$','.diff',$file));
  115.         @unlink(ereg_replace('\.phpt$','.log',$file));
  116.         @unlink(ereg_replace('\.phpt$','.exp',$file));
  117.         @unlink(ereg_replace('\.phpt$','.out',$file));
  118.  
  119.         // Check if test should be skipped.
  120.         $info = '';
  121.         $warn = false;
  122.         if (array_key_exists('SKIPIF', $section_text)) {
  123.             if (trim($section_text['SKIPIF'])) {
  124.                 $this->save_text($tmp_skipif, $section_text['SKIPIF']);
  125.                 //$extra = substr(PHP_OS, 0, 3) !== "WIN" ?
  126.                 //    "unset REQUEST_METHOD;": "";
  127.  
  128.                 //$output = `$extra $php $info_params -f $tmp_skipif`;
  129.                 $output = `$php $info_params -f $tmp_skipif`;
  130.                 unlink($tmp_skipif);
  131.                 if (eregi("^skip", trim($output))) {
  132.                     $skipreason = "SKIP $tested";
  133.                     $reason = (eregi("^skip[[:space:]]*(.+)\$", trim($output))) ? eregi_replace("^skip[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE;
  134.                     if ($reason) {
  135.                         $skipreason .= " (reason: $reason)";
  136.                     }
  137.                     $this->_logger->log(0, $skipreason);
  138.                     if (isset($old_php)) {
  139.                         $php = $old_php;
  140.                     }
  141.                     return 'SKIPPED';
  142.                 }
  143.                 if (eregi("^info", trim($output))) {
  144.                     $reason = (ereg("^info[[:space:]]*(.+)\$", trim($output))) ? ereg_replace("^info[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE;
  145.                     if ($reason) {
  146.                         $info = " (info: $reason)";
  147.                     }
  148.                 }
  149.                 if (eregi("^warn", trim($output))) {
  150.                     $reason = (ereg("^warn[[:space:]]*(.+)\$", trim($output))) ? ereg_replace("^warn[[:space:]]*(.+)\$", "\\1", trim($output)) : FALSE;
  151.                     if ($reason) {
  152.                         $warn = true; /* only if there is a reason */
  153.                         $info = " (warn: $reason)";
  154.                     }
  155.                 }
  156.             }
  157.         }
  158.  
  159.         // We've satisfied the preconditions - run the test!
  160.         $this->save_text($tmp_file,$section_text['FILE']);
  161.  
  162.         $args = $section_text['ARGS'] ? ' -- '.$section_text['ARGS'] : '';
  163.  
  164.         $cmd = "$php$ini_settings -f $tmp_file$args 2>&1";
  165.         if (isset($this->_logger)) {
  166.             $this->_logger->log(2, 'Running command "' . $cmd . '"');
  167.         }
  168.  
  169.         $savedir = getcwd(); // in case the test moves us around
  170.         if (isset($section_text['RETURNS'])) {
  171.             ob_start();
  172.             system($cmd, $return_value);
  173.             $out = ob_get_contents();
  174.             ob_end_clean();
  175.             @unlink($tmp_post);
  176.             $section_text['RETURNS'] = (int) trim($section_text['RETURNS']);
  177.             $returnfail = ($return_value != $section_text['RETURNS']);
  178.         } else {
  179.             $out = `$cmd`;
  180.             $returnfail = false;
  181.         }
  182.         chdir($savedir);
  183.         // Does the output match what is expected?
  184.         $output = trim($out);
  185.         $output = preg_replace('/\r\n/', "\n", $output);
  186.  
  187.         if (isset($section_text['EXPECTF']) || isset($section_text['EXPECTREGEX'])) {
  188.             if (isset($section_text['EXPECTF'])) {
  189.                 $wanted = trim($section_text['EXPECTF']);
  190.             } else {
  191.                 $wanted = trim($section_text['EXPECTREGEX']);
  192.             }
  193.             $wanted_re = preg_replace('/\r\n/',"\n",$wanted);
  194.             if (isset($section_text['EXPECTF'])) {
  195.                 $wanted_re = preg_quote($wanted_re, '/');
  196.                 // Stick to basics
  197.                 $wanted_re = str_replace("%s", ".+?", $wanted_re); //not greedy
  198.                 $wanted_re = str_replace("%i", "[+\-]?[0-9]+", $wanted_re);
  199.                 $wanted_re = str_replace("%d", "[0-9]+", $wanted_re);
  200.                 $wanted_re = str_replace("%x", "[0-9a-fA-F]+", $wanted_re);
  201.                 $wanted_re = str_replace("%f", "[+\-]?\.?[0-9]+\.?[0-9]*(E-?[0-9]+)?", $wanted_re);
  202.                 $wanted_re = str_replace("%c", ".", $wanted_re);
  203.                 // %f allows two points "-.0.0" but that is the best *simple* expression
  204.             }
  205.     /* DEBUG YOUR REGEX HERE
  206.             var_dump($wanted_re);
  207.             print(str_repeat('=', 80) . "\n");
  208.             var_dump($output);
  209.     */
  210.             if (!$returnfail && preg_match("/^$wanted_re\$/s", $output)) {
  211.                 @unlink($tmp_file);
  212.                 $this->_logger->log(0, "PASS $tested$info");
  213.                 if (isset($old_php)) {
  214.                     $php = $old_php;
  215.                 }
  216.                 return 'PASSED';
  217.             }
  218.  
  219.         } else {
  220.             $wanted = trim($section_text['EXPECT']);
  221.             $wanted = preg_replace('/\r\n/',"\n",$wanted);
  222.         // compare and leave on success
  223.             $ok = (0 == strcmp($output,$wanted));
  224.             if (!$returnfail && $ok) {
  225.                 @unlink($tmp_file);
  226.                 $this->_logger->log(0, "PASS $tested$info");
  227.                 if (isset($old_php)) {
  228.                     $php = $old_php;
  229.                 }
  230.                 return 'PASSED';
  231.             }
  232.         }
  233.  
  234.         // Test failed so we need to report details.
  235.         if ($warn) {
  236.             $this->_logger->log(0, "WARN $tested$info");
  237.         } else {
  238.             $this->_logger->log(0, "FAIL $tested$info");
  239.         }
  240.  
  241.         if (isset($section_text['RETURNS'])) {
  242.             $GLOBALS['__PHP_FAILED_TESTS__'][] = array(
  243.                             'name' => $file,
  244.                             'test_name' => $tested,
  245.                             'output' => ereg_replace('\.phpt$','.log', $file),
  246.                             'diff'   => ereg_replace('\.phpt$','.diff', $file),
  247.                             'info'   => $info,
  248.                             'return' => $return_value
  249.                             );
  250.         } else {
  251.             $GLOBALS['__PHP_FAILED_TESTS__'][] = array(
  252.                             'name' => $file,
  253.                             'test_name' => $tested,
  254.                             'output' => ereg_replace('\.phpt$','.log', $file),
  255.                             'diff'   => ereg_replace('\.phpt$','.diff', $file),
  256.                             'info'   => $info,
  257.                             );
  258.         }
  259.  
  260.         // write .exp
  261.         if (strpos($log_format,'E') !== FALSE) {
  262.             $logname = ereg_replace('\.phpt$','.exp',$file);
  263.             if (!$log = fopen($logname,'w')) {
  264.                 return PEAR::raiseError("Cannot create test log - $logname");
  265.             }
  266.             fwrite($log,$wanted);
  267.             fclose($log);
  268.         }
  269.  
  270.         // write .out
  271.         if (strpos($log_format,'O') !== FALSE) {
  272.             $logname = ereg_replace('\.phpt$','.out',$file);
  273.             if (!$log = fopen($logname,'w')) {
  274.                 return PEAR::raiseError("Cannot create test log - $logname");
  275.             }
  276.             fwrite($log,$output);
  277.             fclose($log);
  278.         }
  279.  
  280.         // write .diff
  281.         if (strpos($log_format,'D') !== FALSE) {
  282.             $logname = ereg_replace('\.phpt$','.diff',$file);
  283.             if (!$log = fopen($logname,'w')) {
  284.                 return PEAR::raiseError("Cannot create test log - $logname");
  285.             }
  286.             fwrite($log, $this->generate_diff($wanted, $output,
  287.                 isset($section_text['RETURNS']) ? array(trim($section_text['RETURNS']),
  288.                     $return_value) : null));
  289.             fclose($log);
  290.         }
  291.  
  292.         // write .log
  293.         if (strpos($log_format,'L') !== FALSE) {
  294.             $logname = ereg_replace('\.phpt$','.log',$file);
  295.             if (!$log = fopen($logname,'w')) {
  296.                 return PEAR::raiseError("Cannot create test log - $logname");
  297.             }
  298.             fwrite($log,"
  299. ---- EXPECTED OUTPUT
  300. $wanted
  301. ---- ACTUAL OUTPUT
  302. $output
  303. ---- FAILED
  304. ");
  305.             if ($returnfail) {
  306.                 fwrite($log,"
  307. ---- EXPECTED RETURN
  308. $section_text[RETURNS]
  309. ---- ACTUAL RETURN
  310. $return_value
  311. ");
  312.             }
  313.             fclose($log);
  314.             //error_report($file,$logname,$tested);
  315.         }
  316.  
  317.         if (isset($old_php)) {
  318.             $php = $old_php;
  319.         }
  320.  
  321.         return $warn ? 'WARNED' : 'FAILED';
  322.     }
  323.  
  324.     function generate_diff($wanted, $output, $return_value)
  325.     {
  326.         $w = explode("\n", $wanted);
  327.         $o = explode("\n", $output);
  328.         $w1 = array_diff_assoc($w,$o);
  329.         $o1 = array_diff_assoc($o,$w);
  330.         $w2 = array();
  331.         $o2 = array();
  332.         foreach($w1 as $idx => $val) $w2[sprintf("%03d<",$idx)] = sprintf("%03d- ", $idx+1).$val;
  333.         foreach($o1 as $idx => $val) $o2[sprintf("%03d>",$idx)] = sprintf("%03d+ ", $idx+1).$val;
  334.         $diff = array_merge($w2, $o2);
  335.         ksort($diff);
  336.         if ($return_value) {
  337.             $extra = "##EXPECTED: $return_value[0]\r\n##RETURNED: $return_value[1]";
  338.         } else {
  339.             $extra = '';
  340.         }
  341.         return implode("\r\n", $diff) . $extra;
  342.     }
  343.  
  344.     //
  345.     //  Write the given text to a temporary file, and return the filename.
  346.     //
  347.  
  348.     function save_text($filename, $text)
  349.     {
  350.         if (!$fp = fopen($filename, 'w')) {
  351.             return PEAR::raiseError("Cannot open file '" . $filename . "' (save_text)");
  352.         }
  353.         fwrite($fp,$text);
  354.         fclose($fp);
  355.     if (1 < DETAILED) echo "
  356. FILE $filename {{{
  357. $text
  358. }}}
  359. ";
  360.     }
  361.  
  362. }
  363. ?>

Documentation generated on Mon, 11 Mar 2019 14:24:00 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.