diff options
Diffstat (limited to 'scripts/dev/generate_phpt.php')
| -rw-r--r-- | scripts/dev/generate_phpt.php | 1148 |
1 files changed, 0 insertions, 1148 deletions
diff --git a/scripts/dev/generate_phpt.php b/scripts/dev/generate_phpt.php deleted file mode 100644 index 24b08b942b..0000000000 --- a/scripts/dev/generate_phpt.php +++ /dev/null @@ -1,1148 +0,0 @@ -<?php -/* This is a script which generates simple PHPT test cases from the name of the function. - * It works using the {{{ proto for the function PHP source code. The test cases that it generates - * are simple, however you can also give it the name of a file with PHP code in and it will turn this - * into the right format for a PHPT test. - * This script will not generate expected output. - * Further quidance on how to use it can be found on qa.php.net, or by using the -h command line option. - */ - -//read the command line input and parse it, do some basic checks to make sure that it's correct - -$opt = initialise_opt(); -$opt = parse_args($argv, $opt); - -check_source($opt['source_loc']); -check_fname($opt['name']); -check_testcase($opt['error_gen'], $opt['basic_gen'],$opt['variation_gen']); - -if ($opt['include_block'] != NULL) { - check_file($opt['include_block']); -} - - -//Get a list of all the c funtions in the source tree - -$all_c = array(); -$c_file_count = 0; -dirlist($opt['source_loc'], $c_file_count, $all_c); - - -//Search the list of c functions for the function prototype, quit if can't find it or if the function is an alias - -$test_info = get_loc_proto($all_c, $opt['name'], $opt['source_loc']); - -if (!$test_info['found']) { - echo "\nExiting: Unable to find implementation of {$opt['name']} in {$opt['source_loc']}\n"; - if ($test_info['falias']) { - //But it may be aliased to something else - echo "\n{$test_info['name']}() is an alias of {$test_info['alias']}() --- Write test cases for this instead \n"; - } - exit(); -} -if ($test_info['falias']) { - //If this function is falias'd to another function tell the test case writer about them - echo "\nNote: {$test_info['name']}() is an alias of {$test_info['alias']}() \n"; -} -if ($test_info['error'] != NULL) { - echo $test_info['error']."\n"; - exit(); -} - -$test_info['proto'] = $test_info['return_type']." ". $test_info['name']."(".$test_info['params'].")"; - - -//Set the test sections array - may want more in this later? - -$sections = array('--TEST--', - '--FILE--', - '--EXPECTF--' - ); - -//Parse the parameter list to get the information we need to build code - -$names = array(); -$types = array(); -$num_opt_args = 0; -$num_args = 0; - -$parse_success = parse_params($test_info['params'], $names, $types, $num_args, $num_opt_args); - -if(!$parse_success) { - echo "Unable to parse function parameter list: {$test_info['params']}. Will only generate template test\n"; -} - -if((!$parse_success) || ($opt['include_block'] != NULL)) { - //EITHER - // parse_params returns false (failed) so just generate template code - // OR - // If the user has given a file to import PHP code from - don't attempt to generate code - // - echo "\nGenerating test case for ".$test_info['name']."()\n\n"; - if($opt['basic_gen']) { - $test_case = gen_template($test_info, $sections, 'basic', $opt['include_block']); - } - elseif ($opt['error_gen']) { - $test_case = gen_template($test_info, $sections, 'error', $opt['include_block']); - } - elseif ($opt['variation_gen']) { - $test_case = gen_template($test_info, $sections, 'variation', $opt['include_block']); - } - exit(); -} - - -// parse params succeded - so set up the function arguments to be used in test generation - -$test_info['arg_c'] = $num_args; -$test_info['optional_args'] = $num_opt_args; -if ($num_args > 0) { - $test_info['arg_det'] = array_combine($names, $types); -} - -/* DEBUG HERE - var_dump($test_info); - exit(); -*/ - - -// Ready to generate test cases as required - -echo "\nGenerating test case for ".$test_info['name']."()\n\n"; -$test_case = array(); -if($opt['basic_gen']) { - $test_case = gen_basic_test($test_info, $sections, $test_case); -} -elseif ($opt['error_gen']) { - $test_case = gen_error_test($test_info, $sections, $test_case); -} -elseif ($opt['variation_gen']) { - //generates a number of tests - gen_variation_test($test_info, $sections); -} -/* - * END OF MAIN CODE SECTION - */ -/* - * Function to read the contents of a PHP into an array - * Arguments: - * File name => file name with PHP code in it - * $test_case => test case array to be appended to - * Returns: - * $test_case - */ -function read_include_file($file_name, $test_case) { - $fp = fopen($file_name, "r"); - - $code_block = file($file_name); - - fclose($fp); - - //strip PHP tags and blank lines from start of file - foreach ($code_block as $line) { - if (preg_match("/<\?php/", $line)){ - array_shift($code_block); - break; - }else if(preg_match("/^\s*$/",$line)) { - array_shift($code_block); - }else { - break; - } - } - - //Strip PHP tags and blank lines from the end of the code - $last = count($code_block) -1; - for($j = 0; $j <= $last; $j++) { - $i = $last - $j; - $line = $code_block[$i]; - if(preg_match("/\?>/", $line)) { - array_pop($code_block); - break; - }else if(preg_match("/^\s*$/",$line)) { - array_pop($code_block); - }else { - break; - } - - } - - // Append the lines of code to the test case array and return - foreach($code_block as $line) { - array_push($test_case, $line); - } - return $test_case; -} - -/* - * Generates basic functionality testcase and writes it out to a file. - * Arguments: - * $fn_det => array containing details of the function, - * $sections => The test case sections (eg --TEST--) as an array - * The test case code as arrays keyed by section. - * Returns: - * The test case code as an array of arrays, indexed by section - */ -function gen_basic_test($fn_det, $sections, $test_case) { - $name = $fn_det['name']; - $proto = $fn_det['proto']; - $desc = $fn_det['desc']; - $source_file = $fn_det['source_file']; - $arg_det = $fn_det['arg_det']; - $arg_c = $fn_det['arg_c']; - $optional_args = $fn_det['optional_args']; - $alias = $fn_det['alias']; - - // get the test header - $test_case = gen_test_header($name, $proto, $desc, $source_file, "basic functionality", NULL, $alias, $test_case); - - $test_case['--FILE--'] = gen_basic_test_code($name, $arg_det, $arg_c, $optional_args, $test_case['--FILE--']); - - //End the script - $test_case = gen_test_trailer($test_case,'--EXPECTF--'); - write_file($test_case, $name, 'basic', $sections); - return($test_case); -} -/* - * Function to scan recursively down a directory structure looking for all c files. - * Input: - * $dir - string path of top level directory - * &$c_file_count - reference to a count of the number of files - init to 0, is updated with count after code is run - * &$all_c - reference to list of all c files. Initialise to array, will contain file list after code is run - * Output: - * $all_c (see above) - * $c_file_count (see above) - */ -function dirlist($dir, &$c_file_count, &$all_c) -{ - $thisdir = dir($dir.'/'); //include the trailing slash - while(($file = $thisdir->read()) !== false) { - if ($file != '.' && $file != '..') { - $path = $thisdir->path.$file; - if(is_dir($path) == true) { - dirlist($path , $c_file_count , $all_c); - } else { - if (preg_match("/\w+\.c$/", $file)) { - $all_c[$c_file_count] = $path; - $c_file_count++; - } - } - } - } -return; -} -/* - * Function takes parameter list extracted from the proto comment and retuns a list - * of names and types - * Arguments: - * $param_list (string) = > list of arguments and types - * $names => reference to an array of variable names - * $types => reference to an array of variable - * $nm_args => reference to number of function argumants - * $num_opt_args => reference to number of optional arguments - * Returns: - * True if have been able to parse string $param_list, false if not. - */ -function parse_params($param_list, &$names, &$types, &$num_args, &$num_opt_args) { - $opt_args = false; - $num_mand_args =0; - $num_opt_args = 0; - $num_args = 0; - $opt_params = NULL; - - //remove all commas - $param_list = preg_replace("/,/", "", $param_list); - - //deal with void - if(preg_match("/\s*void\s*/", $param_list)) { - return true; - } - - // extract mandatory parameters and optional parameters - if (preg_match("/^(.*?)\[\s*(.*)\]\s*(.*?)$/", $param_list, $matches)) { - $param_list = $matches[1].$matches[3]; - $opt_params = $matches[2]; - - // Extract nested optional parameters - $temp_opt_params = $opt_params; - while (preg_match("/(.+?)\s*\[\s*(.*)\]/",$temp_opt_params, $matches)) { - $opt_params = $matches[1]." ".$matches[2]; - $temp_opt_params = $opt_params; - } - } - - // seperate parameter list into array of types and names - if ($param_list != "") { - $param_list = chop($param_list); - $param_array = explode(" ", $param_list); - - $num_mand_args = count($param_array)/2; - //check that this is an even number and quit if not, means we have failed to parse correctly - if((round($num_mand_args) * 2) != count($param_array)) {return false;} - - $j = 0; - for($i=0; $i<count($param_array); $i=$i+2) { - $j = $i + 1; - $types[$i] = $param_array[$i]; - // If the variable is a reference remove the & from the variable name - $names[$i] = preg_replace("/&/", "", $param_array[$j]); - } - } - //initialise optional arguments - if ($opt_params != NULL) { - $opt_array = explode(" ", $opt_params); - - $num_opt_args = count($opt_array)/2; - //check that this is an even number and quit if not, means we have failed to parse correctly - if((round($num_opt_args) * 2) != count($opt_array)) {return false;} - - $j = 0; - for($i=0; $i<count($opt_array); $i=$i+2) { - $j = $i + 1; - array_push($types, $opt_array[$i]); - // If the variable is a reference remove the & from the variable name - array_push($names, preg_replace("/&/", "", $opt_array[$j])); - } - } - $num_args = $num_mand_args + $num_opt_args; - return true; -} -/* - * Generates code for an array which contains invalid data types. - * For example, if the variable being tested is of type "float" this code will - * generate an array of data whose type does not include float - * - * Arguments: - * $array_name => name of the array that should be returned - * $var_type => data type of the argument - * Array of code - will be appended to - * Returns: - * $code_block with appended lines of code to initialse the array of data - */ -function gen_array_with_diff_values($var_type, $array_name, $code_block) { - //generate the array with all different values, skip those of the same type as $var_type - - // integer values - $variation_array['int'] = array( - "'int 0' => 0", - "'int 1' => 1", - "'int 12345' => 12345", - "'int -12345' => -2345" - ); - - // float values - $variation_array['float'] = array( - "'float 10.5' => 10.5", - "'float -10.5' => -10.5", - "'float 12.3456789000e10' => 12.3456789000e10", - "'float -12.3456789000e10' => -12.3456789000e10", - "'float .5' => .5" - ); - - // array values - $variation_array['array'] = array( - "'empty array' => array()", - "'int indexed array' => \$index_array", - "'associative array' => \$assoc_array", - "'nested arrays' => array('foo', \$index_array, \$assoc_array)", - ); - - // null vlaues - $variation_array['null'] = array( - "'uppercase NULL' => NULL", - "'lowercase null' => null" - ); - - // boolean values - $variation_array['boolean'] = array( - "'lowercase true' => true", - "'lowercase false' =>false", - "'uppercase TRUE' =>TRUE", - "'uppercase FALSE' =>FALSE" - ); - - // empty data - $variation_array['empty'] = array( - "'empty string DQ' => \"\"", - "'empty string SQ' => ''" - ); - - // string values - $variation_array['string'] = array( - "'string DQ' => \"string\"", - "'string SQ' => 'string'", - "'mixed case string' => \"sTrInG\"", - "'heredoc' => \$heredoc" - ); - - // object data - $variation_array['object'] = array( - "'instance of classWithToString' => new classWithToString()", - "'instance of classWithoutToString' => new classWithoutToString()" - ); - - - // undefined variable - $variation_array['undefined'] = array( - "'undefined var' => @\$undefined_var" - ); - - // unset variable - $variation_array['unset'] = array( - "'unset var' => @\$unset_var" - ); - - - //Write out the code block for the variation array - $blank_line = ""; - array_push($code_block, "\$$array_name = array("); - foreach ($variation_array as $type => $data) { - if($type != $var_type) { - array_push($code_block, $blank_line); - $comment = " // $type data"; - array_push($code_block,$comment); - foreach ($variation_array[$type] as $entry) { - $line = " ".$entry.","; - array_push($code_block, $line); - } - } - } - array_push($code_block, ");"); - return $code_block; -} - -/* - * Generate variation testcases and writes them to file(s) - * 1) generate variation for each argument where different invalid argument values are passed - * 2) generate a vartiation template - * Arguments: - * $fn_det => array containing details of the function, - * $sections => list of test sections, eg '--TEST--', etc - * Returns: - * Nothing at the moment - should be tru for success/false for fail? - * -*/ -function gen_variation_test($fn_det, $sections) { - - $name = $fn_det['name']; - $proto = $fn_det['proto']; - $desc = $fn_det['desc']; - $source_file = $fn_det['source_file']; - $arg_det = $fn_det['arg_det']; - $arg_c = $fn_det['arg_c']; - $optional_args = $fn_det['optional_args']; - $alias = $fn_det['alias']; - - $test_case = array(); - - $test_case = gen_template($fn_det, $sections, 'variation'); - - // if the function has zero argument then quit here because we only need the template - if($arg_c == 0) { - return; - } - - // generate a sequence of other tests which loop over each function arg trying different values - $name_seq = 1; - $arg_count = 1; - if($arg_c > 0) { - for($i = 0; $i < $arg_c; $i++) { - //generate a different variation test case for each argument - $test_case = array(); - - $test_case = gen_test_header($name, $proto, $desc, - $source_file, "usage variation","", $alias, $test_case); - - // add variation code - $test_case['--FILE--'] = gen_variation_diff_arg_values_test($name, $arg_det, $arg_count, $test_case['--FILE--']); - - // end the script - $test_case = gen_test_trailer($test_case, '--EXPECTF--'); - $tc_name = 'variation'.$name_seq; - write_file($test_case, $name, $tc_name, $sections); - - $arg_count ++; // next time generate the code for next argument of the function; - $name_seq ++; // next seqence number for variation test name - } - } -} -/* - * Generate code for testcase header. The following test sections are added: - * --TEST-- & --FILE-- - * Arguments: - * $fn_name => name of the function - * $proto => $fn_name function prototype - * $desc => short description of $fn_name function - * $source_file => location of the file that implements $fn_name function - * $type_msg => Message to indicate what type of testing is being done : "error_conditions", "basic functionality", etc - * $extra_msg => Additional message that will be printed to indicate what specifics are being tested in this file. - * $alias => list any functions that are aliased to this - * $test_sections => an array of arays of testcase code, keyed by section - * Returns: - * $test_sections - */ -function gen_test_header($fn_name, $proto, $desc, $source_file, $type_msg, $extra_msg, $alias, $test_sections) { - $msg = "$type_msg"; - if($extra_msg != NULL) - $msg = "$msg - $extra_msg"; - - - - $test_sections['--TEST--'] = array("Test $fn_name() function : $type_msg $extra_msg" - ); - - $test_sections['--FILE--'] = array ("<?php", - "/* Prototype : $proto", - " * Description: $desc", - " * Source code: $source_file", - " * Alias to functions: $alias", - " */", - "", - "echo \"*** Testing $fn_name() : $type_msg ***\\n\";", - "" - ); - - return $test_sections; -} -/* - * Generate error testcase and writes it to a file - * 1. Generates more than expected no. of argument case - * 2. Generates less than expected no. of argument case - * Arguments: - * $fn_det => array containing details of the function - * $sections => The test case sections (eg --TEST--) as amn array - * $test_case => The test case code as arrays keyed by section. - * Returns: - * The test case code as an array of arrays, indexed by section - */ -function gen_error_test($fn_det, $sections, $test_case) { - $name = $fn_det['name']; - $proto = $fn_det['proto']; - $desc = $fn_det['desc']; - $source_file = $fn_det['source_file']; - $arg_det = $fn_det['arg_det']; - $arg_c = $fn_det['arg_c']; - $optional_args = $fn_det['optional_args']; - $alias = $fn_det['alias']; - - - // get the test header - $test_case = gen_test_header($name, $proto, $desc, $source_file, "error conditions", NULL, $alias, $test_case); - - if($fn_det['arg_c'] == 0 ) { - //If the function expects zero arguments generate a one arg test case and quit - $test_case['--FILE--'] = gen_one_arg_code($name, "extra_arg", "int" , $test_case['--FILE--']); - - } else if (($fn_det['arg_c'] - $fn_det['optional_args']) == 1) { - //If the function expects one argument generate a zero arg test case and two arg test case - $test_case['--FILE--'] = gen_zero_arg_error_case($name, $test_case['--FILE--']); - $test_case['--FILE--'] = gen_morethanexpected_arg_error_case($name, $arg_det, $test_case['--FILE--']); - } else { - $test_case['--FILE--'] = gen_morethanexpected_arg_error_case($name, $arg_det, $test_case['--FILE--']); - $test_case['--FILE--'] = gen_lessthanexpected_arg_error_case($name, $arg_det, $arg_c, $optional_args, $test_case['--FILE--']); - } - // End the script - $test_case = gen_test_trailer($test_case, '--EXPECTF--'); - write_file($test_case, $name, 'error', $sections); - return($test_case); -} -/* - * Add the final lines of the testcase, the default is set to be EXPECTF. - * Arguments: - * $test_case - An aray of arrays keyed by test section - * $section_key - Type of EXPECT section, defaults to EXPECTF - * Returns: - * $test_case - completed test cases code as an array of arrays keyed by section - */ -function gen_test_trailer($test_case, $section_key = "--EXPECTF--") { - //Complete the --FILE-- section - array_push($test_case['--FILE--'], ""); - array_push($test_case['--FILE--'], "?>\n===DONE==="); - - //add a new key for the expect section - $test_case[$section_key]=array(); - array_push($test_case[$section_key], "Expected output goes here"); - array_push($test_case[$section_key], "===DONE==="); - - return $test_case; -} -/* - * Writes test case code to a file - * Arguments: - * $test_case => Array of arrays of test sections, keyed by section - * $function_name => Name of functio that tests are being generated for - * $type => basic/error/variation - * $test_sections => keys to $test_case - * $seq = > sequence number, may be appended to file name - * Returns: - * Nothing at the moment - should be true/false depending on success - */ -function write_file($test_case, $function_name, $type, $test_sections, $seq="") { - $file_name = $function_name."_".$type.$seq.".phpt"; - - $fp = fopen($file_name, 'w'); - - foreach($test_sections as $section) { - if(array_key_exists($section, $test_case)) { - fwrite($fp, $section."\n"); - if(count($test_case[$section]) >0 ){ - foreach($test_case[$section] as $line_of_code) { - fwrite($fp, $line_of_code."\n"); - } - } - } - } - fclose($fp); -} -/* - * Generate code for testing different invalid values against an argument of the function - * Arguments: - * $fn_name => name of the function - * $arg_det => details of the each argument, stored in an array in the form of 'nameofargument' => 'typeofargument' - * $which_arg => a numeric value starting from 1 indicating the argument of the - * function ( in $arg_det ) for which the case needs to be generated - * $code_block => array of code which will be appended to - * Returns: - * $code_block - */ -function gen_variation_diff_arg_values_test($fn_name, $arg_det, $which_arg, $code_block) { - - $names = array_keys($arg_det); - $types = array_values($arg_det); - - $blank_line = ""; - - // decrement the $which_arg so that its matches with the index of $types - $which_arg--; - - //generate code to define error handler - $code_block = add_error_handler($code_block); - - // generate code to initialise arguments that won't be substituted - array_push($code_block, "// Initialise function arguments not being substituted (if any)"); - for($i = 0; $i < count($types); $i ++) { - if ($i != $which_arg) { // do not generate initialization code for the argument which is being tested - $i_stmt = get_variable_init_statement($types[$i], $names[$i]); - array_push($code_block, $i_stmt); - } - } - array_push($code_block, $blank_line); - - - // generate code to unset a variable - array_push($code_block, "//get an unset variable"); - array_push($code_block, "\$unset_var = 10;"); - array_push($code_block, "unset (\$unset_var);"); - array_push($code_block, $blank_line); - - //define some classes - $code_block = define_classes($code_block); - - //add heredoc string - array_push($code_block, "// heredoc string"); - array_push($code_block, "\$heredoc = <<<EOT"); - array_push($code_block, "hello world"); - array_push($code_block, "EOT;"); - array_push($code_block, $blank_line); - - //add arrays - array_push($code_block, "// add arrays"); - array_push($code_block, "\$index_array = array (1, 2, 3);"); - array_push($code_block, "\$assoc_array = array ('one' => 1, 'two' => 2);"); - array_push($code_block, $blank_line); - - - //generate code for an array of values to iterate over - array_push($code_block, "//array of values to iterate over"); - $code_block = gen_array_with_diff_values($types[$which_arg], 'inputs', $code_block); - - //generate code for loop to iterate over array values - array_push($code_block, $blank_line); - - array_push($code_block, "// loop through each element of the array for $names[$which_arg]"); - array_push($code_block, $blank_line); - - array_push($code_block, "foreach(\$inputs as \$key =>\$value) {"); - array_push($code_block, " echo \"\\n--\$key--\\n\";"); - - // prepare the function call - - // use all arguments including the optional ones to construct a single function call - $var_name = array(); - foreach ($names as $nm) { - array_push($var_name, "$".$nm); - } - $var_name[$which_arg] = "\$value"; - $all_args = implode(", ", $var_name); - - array_push ($code_block, " var_dump( $fn_name($all_args) );"); - array_push ($code_block, "};"); - - - return $code_block; -} -/* - * Generate code for testing more than expected no. of argument for error testcase - * Arguments: - * $fn_name => name of the function - * $arg_det => details of the each argument, stored in an array in the form of 'nameofargument' => 'typeofargument' - * $code_block => an array of code that will be appended to - * Returns: - * $code_block - */ -function gen_morethanexpected_arg_error_case($fn_name, $arg_det ,$code_block) { - array_push($code_block, ""); - array_push($code_block, "//Test $fn_name with one more than the expected number of arguments"); - array_push($code_block, "echo \"\\n-- Testing $fn_name() function with more than expected no. of arguments --\\n\";"); - - $names = array_keys($arg_det); - $types = array_values($arg_det); - - //Initialise expected arguments - for($i = 0; $i < count($types); $i ++) { - $i_stmt = get_variable_init_statement($types[$i], $names[$i]); - array_push($code_block, $i_stmt); - } - - // get the extra argument init statement - $i_stmt = get_variable_init_statement("int", "extra_arg"); - array_push($code_block, $i_stmt); - - $var_name = array(); - foreach ($names as $nm) { - array_push($var_name, "$".$nm); - } - $all_args = implode(", ", $var_name); - - array_push($code_block, "var_dump( $fn_name($all_args, \$extra_arg) );"); - - return $code_block; -} - -/* - * Generate code for testing less than expected no. of mandatory arguments for error testcase - * Arguments: - * $fn_name => name of the function - * $arg_det => details of the each argument, stored in an array in the form of 'nameofargument' => 'typeofargument' - * $arg_c => total count of arguments that $fn_name takes - * $optional_args => total count of optional arguments that $fn_name takes - * $code_block => an array of code that will be appended to - * Returns: - * $code_block - */ -function gen_lessthanexpected_arg_error_case($fn_name, $arg_det, $arg_c, $optional_args, $code_block) { - - $names = array_keys($arg_det); - $types = array_values($arg_det); - - // check for no. of mandatory arguments - // if there are no mandatory arguments - return - // the code_block unchanged - $mandatory_args = $arg_c - $optional_args; - if($mandatory_args < 1) { - return ($code_block); - } - - //Discard optional arguments and last mandatory arg - for ($i = 0; $i < $optional_args; $i++) { - $discard_n = array_pop($names); - $discard_v = array_pop($types); - } - $discard_n = array_pop($names); - $discard_v = array_pop($types); - - array_push($code_block, ""); - array_push($code_block, "// Testing $fn_name with one less than the expected number of arguments"); - array_push($code_block, "echo \"\\n-- Testing $fn_name() function with less than expected no. of arguments --\\n\";"); - - for($i = 0; $i < count($names); $i ++) { - $i_stmt = get_variable_init_statement($types[$i], $names[$i]); - array_push($code_block, $i_stmt); - } - - $all_args = ""; - if ($mandatory_args > 1) { - $var_name = array(); - foreach ($names as $nm) { - array_push($var_name, "$".$nm); - } - $all_args = implode(", ", $var_name); - } - - array_push($code_block, "var_dump( $fn_name($all_args) );"); - - return $code_block; -} -/* - * Generates code for initalizing a given variable with value of same type - * Arguments: - * $var_type => data type of variable - * $var_name => name of the variable - * Returns: - * $code_block - */ -function get_variable_init_statement( $var_type, $var_name ) { - $code = ""; - if ($var_type == "int") { - $code = "\$$var_name = 10;"; - } else if($var_type == "float") { - $code = "\$$var_name = 10.5;"; - } else if($var_type == "array") { - $code = "\$$var_name = array(1, 2);"; - } else if($var_type == "string") { - $code = "\$$var_name = 'string_val';"; - } else if($var_type == "object") { - $code = "\$$var_name = new stdclass();"; - } else if($var_type == 'bool' || $var_type == 'boolean') { - $code = "\$$var_name = true;"; - } else if($var_type == 'mixed') { - // take a guess at int - $code = "\$$var_name = 1;"; - } else { - $code = "\n//WARNING: Unable to initialise $var_name of type $var_type\n"; -} - return $code; -} -/* - * Generate code for function with one argument - * Arguments: - * $fn_name => name of the function - * $arg_name => name of the argument - * $arg_type => data type of the argument - * $code_block => an array of code that will be appended to - * Returns: - * $code_block - */ -function gen_one_arg_code($fn_name, $arg_name, $arg_type, $code_block) { - //Initialse the argument - $arg_one_init = get_variable_init_statement($arg_type, $arg_name); - - //push code onto the array $code_block - array_push ($code_block, "// One argument"); - array_push ($code_block, "echo \"\\n-- Testing $fn_name() function with one argument --\\n\";"); - array_push ($code_block, "$arg_one_init;"); - array_push ($code_block, "var_dump( $fn_name(\$$arg_name) );"); - return $code_block; -} -/* - * Generates code for basic functionality test. The generated code - * will test the function with it's mandatory arguments and with all optional arguments. - * Arguments: - * $fn_name => name of the function - * $arg_det => details of the each argument, stored in an array in the form of 'nameofargument' => 'typeofargument' - * $arg_c => total count of arguments that $fn_name takes - * $optional_args. $optional_args => total count of optional arguments that $fn_name takes - * $code_block - an array of code that will be appended to - * Returns: - * $code_block with appends - */ -function gen_basic_test_code($fn_name, $arg_det, $arg_c, $optional_args, $code_block) { - if($arg_c == 0) { - //Just generate Zero arg test case and return - $code_block = gen_zero_arg_error_case($fn_name, $code_block); - return $code_block; - } - $names = array_keys($arg_det); - $types = array_values($arg_det); - - // prepare code to initialize all reqd. arguments - array_push ($code_block, ""); - array_push ($code_block, "// Initialise all required variables"); - for($i = 0; $i < $arg_c; $i ++) { - $i_stmt = get_variable_init_statement($types[$i], $names[$i]); - array_push($code_block, $i_stmt); - } - - - // prepare the function calls - - // all arguments including the optional ones - $var_name = array(); - foreach ($names as $nm) { - array_push($var_name, "$".$nm); - } - $all_args = implode(", ", $var_name); - - array_push ($code_block, ""); - array_push ($code_block, "// Calling $fn_name() with all possible arguments"); - array_push ($code_block, "var_dump( $fn_name($all_args) );"); - - //now remove the optional arguments and call the function with mandatory arguments only - if ($optional_args != 0) { - for ($i=0; $i < $optional_args; $i++) { - $discard_n = array_pop($var_name); - } - $args = implode(", ", $var_name); - array_push ($code_block, ""); - array_push ($code_block, "// Calling $fn_name() with mandatory arguments"); - array_push ($code_block, "var_dump( $fn_name($args) );"); - } - return $code_block; -} - -/* - * Function to parse command line arguments - * Returns: - * $opt_array => array of options - */ -function initialise_opt() { - $opt=array(); - $opt['source_loc'] = NULL; - $opt['name'] = NULL; - $opt['error_gen'] = false; - $opt['basic_gen'] = false; - $opt['variation_gen'] = false; - $opt['include_block'] = NULL; - return $opt; -} -function parse_args ($arglist, $opt) -{ - for($j = 1; $j<count($arglist); $j++) { - switch ($arglist[$j]) - { - case '-s': - $j++; - $opt['source_loc'] = $arglist[$j]; - break; - - case '-f': - $j++; - $opt['name'] = $arglist[$j]; - break; - - case '-e': - $opt['error_gen'] = true; - break; - - case '-b': - $opt['basic_gen'] = true; - break; - - case '-v': - $opt['variation_gen'] = true; - break; - - case '-i': - $j++; - $opt['include_block'] = $arglist[$j]; - break; - - case '-h': - print_opts(); - break; - - default: - echo "Command line option $arglist[$j] not recognised\n"; - print_opts(); - } - - } - return $opt; -} -/* - * Function to check that source directory given for PHP source actually conatins PHP source - */ -function check_source($src) -{ - $ext_loc = $src."/ext"; - if(!is_dir($ext_loc)) { - echo "A PHP source location is required, $src does not appear to be a valid source location\n"; - print_opts(); - } -} -/* - * Function to check that a file name exists - */ -function check_file($f) -{ - if(!is_file($f)) { - echo "$f is not a valid file name \n"; - print_opts(); - } -} -/* - * Function to check thet either a file name, a list of files or a function area has been supplied - */ -function check_fname ($f) -{ - if($f == NULL ) { - echo "Require a function name \n"; - print_opts(); - } -} -/* - * Function to check that the user has requested a type of test case - */ -function check_testcase($e, $v, $b) { - if(!$v && !$e && !$b) { - echo "Need to specify which type of test to generate\n"; - print_opts(); - } -} -/* - * Function to print out help text if any of the input data is incorrect - */ -function print_opts() { - echo "\nUsage:\n"; - echo " php generate_phpt.php -s <location_of_source_code> -f <function_name> -b|e|v [-i file]\n\n"; - echo "-s location_of_source_code ....... Top level directory of PHP source\n"; - echo "-f function_name ................. Name of PHP function, eg cos\n"; - echo "-b ............................... Generate basic tests\n"; - echo "-e ............................... Generate error tests\n"; - echo "-v ............................... Generate variation tests\n"; - echo "-i file_containing_include_block.. Block of PHP code to be included in the test case\n"; - echo "-h ............................... Print this message\n"; - exit; -} -/* - * Generates a general testcase template and create the testcase file, - * No code is added other than header and trailer - * Arguments: - * $fn_det => Array with function details - * $sections => List of test sections eg '--TEST--', '--FILE--'.. - * $type => basic/error/variation - * $php_file => name of file to import PHP code from - * Returns: - * $test_case => an array containing the complete test case - */ -function gen_template($fn_det, $sections, $type, $php_file=NULL) { - $name = $fn_det['name']; - $proto = $fn_det['proto']; - $desc = $fn_det['desc']; - $source_file = $fn_det['source_file']; - $alias = $fn_det['alias']; - - $test_case = array(); - - // get the test header and write into the file - $test_case = gen_test_header($name, $proto, $desc, $source_file, $type, "",$alias, $test_case); - - // write the message to indicate the start of addition of code in the template file - if ($php_file == NULl) { - $msg = "\n // add test code here \n"; - array_push($test_case['--FILE--'], $msg); - }else{ - $test_case['--FILE--'] = read_include_file($php_file, $test_case['--FILE--']); - } - - // end the script - $test_case = gen_test_trailer($test_case); - write_file($test_case, $name, $type, $sections); - return ($test_case); -} -/* - * Generate code for testing zero argument case for error testcase - * Arguments: - * $fn_name => name of the function - * $code_block => array of code which will be appended to - * Returns: - * $code_block - */ -function gen_zero_arg_error_case($fn_name, $code_block) { - //push code onto the array $code_block - array_push ($code_block, "// Zero arguments"); - array_push ($code_block, "echo \"\\n-- Testing $fn_name() function with Zero arguments --\\n\";"); - array_push ($code_block, "var_dump( $fn_name() );"); - return $code_block; -} -function get_loc_proto($all_c, $fname, $source) { -//get location - $test_info['name'] = $fname; - $test_info['source_file'] = NULL; - $test_info['return_type'] = NULL; - $test_info['params'] = NULL; - $test_info['falias'] = false; - $test_info['found'] = false; - $test_info['alias'] = NULL; - $test_info['error'] = NULL; - - $escaped_source = preg_replace("/\\\/", "\\\\\\", $source); - $escaped_source = preg_replace("/\//", "\\\/", $escaped_source); - - - for ($i=0; $i<count($all_c); $i++) - { - $strings=file_get_contents(chop($all_c[$i])); - if (preg_match ("/FUNCTION\($fname\)/",$strings)) - { - //strip build specific part of the implementation file name - preg_match("/$escaped_source\/(.*)$/", $all_c[$i], $tmp); - $test_info['source_file'] = $tmp[1]; - //get prototype information - if (preg_match("/\/\*\s+{{{\s*proto\s+(\w*)\s*$fname\(\s*(.*)\s*\)(\n|)\s*(.*?)(\*\/|\n)/", $strings, $matches)) { - $test_info['return_type'] = $matches[1]; - $test_info['params'] = $matches[2]; - $test_info['desc'] = $matches[4]; - } - else { - $test_info['error'] = "\nFailed to parse prototype for $fname in $all_c[$i]". - "\nEither the {{{proto comment is too hard to parse, or ". - "\nthe real implementation is in an alias.\n"; - } - $test_info['found'] = true; - if ((preg_match ("/FALIAS\($fname,\s*(\w+),.*\)/",$strings, $alias_name)) - || (preg_match ("/FALIAS\((\w+),\s*$fname.*\)/",$strings, $alias_name))) { - // There is another alias referred to in the same C source file. Make a note of it. - $test_info['falias'] = true; - if ( $test_info['alias'] != NULL) { - $test_info['alias'] = $test_info['alias']." ".$alias_name[1]; - } else { - $test_info['alias'] = $alias_name[1]; - } - } - } - elseif ((preg_match ("/FALIAS\($fname,\s*(\w+),.*\)/",$strings, $alias_name)) - || (preg_match ("/FALIAS\((\w+),\s*$fname.*\)/",$strings, $alias_name))) { - // There is an alias to the function in a different file from the main function definition - make a note of it - $test_info['falias'] = true; - if ( $test_info['alias'] != NULL) { - $test_info['alias'] = $test_info['alias']." ".$alias_name[1]; - } else { - $test_info['alias'] = $alias_name[1]; - } - } - //Some functions are in their own files and not declared using FUNTION/FALIAS. - //If we haven't found either FUNCTION or FALIAS try just looking for the prototype - elseif (preg_match ("/\/\*\s+{{{\s*proto\s+(\w*)\s*$fname\(\s*(.*)\s*\)(\n|)\s*(.*)\*\//", $strings, $matches)) { - $test_info['return_type'] = $matches[1]; - $test_info['params'] = $matches[2]; - $test_info['desc'] = $matches[4]; - $test_info['found'] = true; - preg_match("/$escaped_source\/(.*)$/", $all_c[$i], $tmp); - $test_info['source_file']= $tmp[1]; - //break; - } - } - return $test_info; -} -function add_error_handler($cb) { - array_push($cb, "// Define error handler"); - array_push($cb, "function test_error_handler(\$err_no, \$err_msg, \$filename, \$linenum, \$vars) {"); - array_push($cb, " if (error_reporting() != 0) {"); - array_push($cb, " // report non-silenced errors"); - array_push($cb, " echo \"Error: \$err_no - \$err_msg, \$filename(\$linenum)\\n\";"); - array_push($cb, " }"); - array_push($cb, "}"); - array_push($cb, "set_error_handler('test_error_handler');"); - array_push($cb, ""); - - return $cb; - -} - -function define_classes($cb) { - array_push($cb,"// define some classes"); - array_push($cb,"class classWithToString"); - array_push($cb,"{"); - array_push($cb," public function __toString() {"); - array_push($cb," return \"Class A object\";"); - array_push($cb," }"); - array_push($cb,"}"); - array_push($cb,""); - array_push($cb,"class classWithoutToString"); - array_push($cb,"{"); - array_push($cb,"}"); - array_push($cb,""); - - return $cb; -} -?> |
