Back to index

php5  5.3.10
find_tested.php
Go to the documentation of this file.
00001 <?php
00002 
00003 
00004 $usage = <<<USAGE
00005 
00006 Usage: php find_tested.php [path_to_test_files] ([extension])
00007 
00008 Outputs test coverage information for functions and methods in csv format.
00009 Supplying an optional extension name outputs only information for functions and methods from that extension.
00010 
00011 Output format:
00012 Extension, Class Name, Method/Function Name, Test Status, Test Files
00013 
00014 A test status of "verify" for a method means that there is at least one other method of the same name, so test coverage must be verified manually.
00015 
00016 USAGE;
00017 
00018 
00019 /* method record fields */
00020 define("CLASS_NAME", "CLASS_NAME");
00021 define("METHOD_NAME", "METHOD_NAME");
00022 define("EXTENSION_NAME", "EXTENSION_NAME");
00023 define("IS_DUPLICATE", "IS_DUPLICATE");
00024 define("IS_TESTED", "IS_TESTED");
00025 define("TESTS", "TESTS");
00026 
00027 
00028 // process command line args
00029 $num_params = $argc;
00030 if ($num_params < 2 || $num_params > 3) {
00031     die($usage);
00032 }
00033 
00034 $extension_test_path = $argv[1];
00035 
00036 if ($num_params == 3) {
00037     $extension_name = $argv[2];
00038 
00039     // check extension exists
00040     $extensions = get_loaded_extensions();
00041     if (!in_array($extension_name, $extensions)) {
00042         echo "Error: extension $extension_name is not loaded. Loaded extensions:\n";
00043         foreach($extensions as $extension) {
00044             echo "$extension\n";
00045         }
00046         die();
00047     }
00048 } else {
00049     $extension_name = false;
00050 }
00051 
00052 
00053 $method_info = populate_method_info();
00054 
00055 if ($extension_name != false) {
00056     // get only the methods from the extension we are querying
00057     $extension_method_info = array();
00058     foreach($method_info as $method_record) {
00059         if (strcasecmp($extension_name, $method_record[EXTENSION_NAME]) == 0) {
00060             $extension_method_info[] = $method_record;
00061         }
00062     }
00063 } else {
00064     $extension_method_info = $method_info;
00065 }
00066 
00067 get_phpt_files($extension_test_path, $count, $phpt_files);
00068 
00069 $extension_method_info = mark_methods_as_tested($extension_method_info, $phpt_files);
00070 
00071 
00072 foreach($extension_method_info as $record) {
00073     echo $record[EXTENSION_NAME] . ",";
00074     echo $record[CLASS_NAME] . ",";
00075     echo $record[METHOD_NAME] . ",";
00076     echo $record[IS_TESTED] . ",";
00077     echo $record[TESTS] . "\n";
00078 }
00079 
00084 function mark_methods_as_tested($method_info, $phpt_files) { 
00085 
00086     foreach($phpt_files as $phpt_file) {
00087         $tested_functions = extract_tests($phpt_file);
00088 
00089         foreach($tested_functions as $tested_function) {
00090 
00091             // go through method info array marking this funtion as tested
00092             foreach($method_info as &$current_method_record) {
00093                 if (strcasecmp($tested_function, $current_method_record[METHOD_NAME]) == 0) {
00094                     // matched the method name
00095                     if ($current_method_record[IS_DUPLICATE] == true) {
00096                         // we cannot be sure which class this method corresponds to,
00097                         // so mark method as needing to be verified 
00098                         $current_method_record[IS_TESTED] = "verify";
00099                     } else {
00100                         $current_method_record[IS_TESTED] = "yes";
00101                     }
00102                     $current_method_record[TESTS] .= $phpt_file . "; ";
00103                 }
00104             }
00105         }
00106     }
00107     return $method_info;
00108 }
00109 
00113 function populate_method_info() {
00114     
00115     $method_info = array();
00116 
00117     // get functions
00118     $all_functions = get_defined_functions();
00119     $internal_functions = $all_functions["internal"];
00120 
00121     foreach ($internal_functions as $function) {
00122         // populate new method record
00123         $function_record = array();
00124         $function_record[CLASS_NAME] = "Function";
00125         $function_record[METHOD_NAME] = $function;
00126         $function_record[IS_TESTED] = "no";
00127         $function_record[TESTS] = "";
00128         $function_record[IS_DUPLICATE] = false;
00129 
00130         // record the extension that the function belongs to
00131         $reflectionFunction = new ReflectionFunction($function);
00132         $extension = $reflectionFunction->getExtension();
00133         if ($extension != null) {
00134             $function_record[EXTENSION_NAME] = $extension->getName();
00135         } else {
00136             $function_record[EXTENSION_NAME] = "";
00137         }
00138         // insert new method record into info array
00139         $method_info[] = $function_record;
00140     }
00141 
00142     // get methods
00143     $all_classes = get_declared_classes();
00144     foreach ($all_classes as $class) {
00145         $reflectionClass = new ReflectionClass($class);
00146         $methods = $reflectionClass->getMethods();
00147         foreach ($methods as $method) {
00148             // populate new method record
00149             $new_method_record = array();
00150             $new_method_record[CLASS_NAME] = $reflectionClass->getName();
00151             $new_method_record[METHOD_NAME] = $method->getName();
00152             $new_method_record[IS_TESTED] = "no";
00153             $new_method_record[TESTS] = "";
00154 
00155             $extension = $reflectionClass->getExtension();
00156             if ($extension != null) {
00157                 $new_method_record[EXTENSION_NAME] = $extension->getName();
00158             } else {
00159                 $new_method_record[EXTENSION_NAME] = "";
00160             }
00161 
00162             // check for duplicate method names
00163             $new_method_record[IS_DUPLICATE] = false;
00164             foreach ($method_info as &$current_record) {
00165                 if (strcmp($current_record[METHOD_NAME], $new_method_record[METHOD_NAME]) == 0) {
00166                     $new_method_record[IS_DUPLICATE] = true;
00167                     $current_record[IS_DUPLICATE] = true;
00168                 }
00169             }
00170             // insert new method record into info array
00171             $method_info[] = $new_method_record;
00172         }
00173     }
00174 
00175     return $method_info;
00176 }
00177 
00178 function get_phpt_files($dir, &$phpt_file_count, &$all_phpt)
00179 {
00180     $thisdir = dir($dir.'/'); //include the trailing slash
00181     while(($file = $thisdir->read()) !== false) {
00182         if ($file != '.' && $file != '..') {
00183             $path = $thisdir->path.$file;
00184             if(is_dir($path) == true) {
00185                 get_phpt_files($path , $phpt_file_count , $all_phpt);
00186             } else {
00187                 if (preg_match("/\w+\.phpt$/", $file)) {
00188                     $all_phpt[$phpt_file_count] = $path;
00189                     $phpt_file_count++;
00190                 }
00191             }
00192         }
00193     }
00194 }
00195 
00196 function  extract_tests($file) {
00197        $code = file_get_contents($file);
00198        
00199        if (!preg_match('/--FILE--\s*(.*)\s*--(EXPECTF|EXPECTREGEX|EXPECT)?--/is', $code, $r)) {
00200 //            print "Unable to get code in ".$file."\n";
00201               return array();
00202        }
00203        
00204        $tokens = token_get_all($r[1]);
00205        $functions = array_filter($tokens, 'filter_functions');
00206        $functions = array_map( 'map_token_value',$functions);
00207        $functions = array_unique($functions);
00208        
00209        return $functions;
00210 }
00211 
00212 function filter_functions($x) {
00213        return $x[0] == 307;
00214 }
00215 
00216 function map_token_value($x) {
00217        return $x[1];
00218 }
00219 
00220 
00221 ?>
00222