From: Sebastien D. <sde...@us...> - 2005-07-05 09:14:51
|
Update of /cvsroot/tslogparser/tslogparser/admin/modules In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv27424/admin/modules Added Files: new.mod.php.template Log Message: New template for plug-ins --- NEW FILE: new.mod.php.template --- <?php /* * Copyright (c) 2005, Bull S.A.. All rights reserved. * Created by: Sebastien Decugis * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * You should have received a copy of the GNU General Public License along * with this program; if not, write the Free Software Foundation, Inc., 59 * Temple Place - Suite 330, Boston MA 02111-1307, USA. */ /* This module can serve as a base for any new module. * It contains the code which will be common to almost all plug-ins. * * Please read the comments carefully to write a new module. */ /* Class name: (here 'newmodule') should be replaced with the name of your module, which will appear everywhere later. double check that this name is the same as at the end of this file (return 'newmodule'). */ class newmodule { function module_info($what="") { /* This routine only returns information about the module. It can contain the version number, information about the author or link to a website. The information is accessed from the interface through: administration -> (this module) about button */ $title = "<b>New</b> parser module for <b>TSLogParser</b>"; $text = "<p>$title</p>\n"; $text.= "<p>Release: <b>0.0</b> 2004/12/31</p>\n"; $text.= "<p>Limitations and known problems: \n"; $text.= "<ul>\n<li>This module is a template for plug-ins; no function is working yet\n"; $text.= "</li></ul></p>\n"; $text.= "<p>See the <a href='http://tslogparser.sourceforge.net/'>homepage</a> for more information.</p>\n"; if ($what == "title") return $title; return $text; } /* The next function is in charge of saving a test suite description (not a logfile!) into the database. The inputs are: $TS_name and $TS_description: information about the release being added. $path: path on the local filesystem where the tarball has been unzipped. The outputs are: In the database, the following tables should be impacted: opts_routines, opts_assertions, opts_versions, opts_version_descriptions More precisely: opts_version receives 1 entry with the $TS_name and $TS_description information. opts_routines and opts_assertions allows to create a hierarchy of the tests opts_version_description receives as many entries as the number of test cases in the test suite. As an example, you can have: the routine pthread_create (in opts_routines) contains 3 assertions (in opts_assertions). The second assertion ('the function creates a thread') contains 4 testcases (in opts_version_description). A good pratice when adding new releases is to check that the routines or assertions are not already in the database, and add only the new ones. On the other hand, when adding a new release, you'll have always new entries in opts_version_description and opts_versions. */ function TS_parse(&$parent, $TS_name, $TS_description, $path) { if ( $parent->debug ) echo "tahi->TS_parse($TS_name, $TS_description, $path)\n"; /* Check that the uploaded file (already untarred) is readable */ if (!is_dir($path) || !($dh = opendir($path))) { $parent->last_error="Directory '$path' is not readable -- check your archive format.\n"; return FALSE; } /* Check this archive contains a correct testsuite. It can for example check that a particular file exists, or a certain structure on which this parser relies. At the same time, one can parse the files and save the tests information (with hierarchy data depending on how you will fit into the routines / assertions / tests model) This is what we call here $NEW_TS. The recommended format (you're free to follow this or not) is: $NEW_TS = array( "routine1" => array ( "routine_comment" => [comment on this routine, extracted from the Test Suite] "assertions" => array( array ( "text" => [text of first assertion] "number" => [id of this assertion] "tests" => array( 1 => [filename of 1st test], 2 => [filename of 2nd test] ) ) array ( "text" => [text of second assertion] "number" => [id of this assertion] "tests" => array( 1 => [filename of 1st test] ) ) ) "routine2" => array ( "routine_comment" => [comment on this routine, extracted from the Test Suite] ... ) ) */ while (($file = readdir($dh)) !== false) { /* ... (check format and then create $NEW_TS) */ } /* If the format was not correct, return an error. For example: */ if (!$format_is_correct) { $parent->last_error="Directory '$path' does not contain a valid test suite -- unable to parse.\n"; return FALSE; } /* The next one is usefull when debugging this function ;) */ if ($parent->debug > 2) print_r($NEW_TS); /* The database shall be initialized here */ if (!is_db_init()) { $parent->last_error="Database was not initialized\n"; return FALSE; } /* Check no release with the same name already exists */ $releases=query_version($TS_name, 1); if ($releases) { $parent->last_error= "The release '$TS_name' is already in the database \n". "<i>(".stringFromDB($releases[$TS_name]["ver_comment"]).")</i>\n"; return FALSE; } /* Ok, here we have checked everything, we should be able to add the testsuite from now on. */ /* First step is to create the list of entries to be added into opts_routines */ $current_routines=query_routines(); /* We start with looking for missing routines */ $missing_routines=array(); /* browse the new release data and find the missing elements */ foreach ($NEW_TS as $routine => $routine_data) { /* If the routine is missing from opts_routines table, we'll add it */ if (!isset($current_routines[$routine])) $missing_routines[]=$routine; else /* check the routine was not renamed from the previous entered version */ /* Here, $routine_data is what we analyzed during the testsuite parsing, and $current_routines come from the database (parsing of previous releases) */ if ($routine_data["routine_comment"] != $current_routines[$routine]["routine_comment"]) { echo "Inconsistency found for routine <b>$routine</b><br>\n"; echo "Old comment: ".$current_routines[$routine]["routine_comment"]."<br>\n"; echo "New comment: ".$routine_data["routine_comment"]."\n"; $parent->last_error= "Unable to add $routine to the database\n"; return FALSE; } } if ($parent->debug > 1) print_r($missing_category); /* If any routine is missing, it must be added previously to further processing */ if ($missing_routines) { echo "New routines are being added to the database...\n"; $counter=0; foreach ($missing_routines as $routine) { $sql = "INSERT INTO opts_routines ( rou_name, rou_comment ) " ."VALUES ( ".stringToDB($routine)."," .stringToDB($NEW_TS[$routine]["routine_comment"])." )"; if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; if (db_execute_insert($sql)) $counter++; else echo "Failed to add $routine to the database...\n"; } echo "Done. <b>$counter</b> categories have been added.\n\n"; $current_routines=query_routines(); } /* Same thing about assertions */ $current_assertions=query_all_asserts(); $missing_assertions=array(); /* Check for existing tests */ foreach ($NEW_TS as $routine => $routine_data) { if (!isset($current_assertions[$routine])) { if (!isset($current_routines[$routine])) { $parent->last_error="Internal script error: routine $routine was not added in 1st pass"; return FALSE; } /* We now schedule addition of these assertions for this routine, as none was already defined */ foreach ($routine_data["assertions"] as $assert_data) { $missing_assertions[]=array( "routine"=>$routine, "assertion"=>&$assert_data["text"], "id" => $assert_data["number"]); } } else /* some assertions were already defined in this routine */ { foreach ($routine_data["assertions"] as $assert_data) { /* Check if this assertion content was already in the database */ if(!in_array($assert_data["text"], $current_assertions[$routine])) $missing_assertions[]=array( "routine"=>$routine, "assertion"=>&$assert_data["text"], "id" => $assert_data["number"]); } } } if ($parent->debug > 1) print_r($missing_assertions); /* If any assertion is missing, it must be added previously to further processing */ if ($missing_assertions) { echo "New assertions are being added to the database...\n"; $counter=0; foreach ($missing_assertions as $assert_data) { $sql = "INSERT INTO opts_assertions ( assert_routine, assert_text ) " ."VALUES ( ".$current_routines[$assert_data["routine"]]["routine_id"]."," .stringToDB($assert_data["assertion"])." )"; if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; if (db_execute_insert($sql)) $counter++; else echo "Failed to add assertion ".$assert_data["id"]." of routine ".$assert_data["routine"]." to the database...\n"; } echo "Done. <b>$counter</b> tests have been added.\n\n"; $current_assertions=query_all_asserts(); } if ($parent->debug > 2) print_r($current_assertions); /* Now we can create the release description in database */ $sql="INSERT INTO opts_versions (ver_name, ver_comment, ver_module) " . "VALUES ( ".stringToDB($TS_name).", " . stringToDB($TS_description).", " . stringToDB("newmodule") ." )"; @/* @@@ Don't forget to change the module name here! */ if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; if (!db_execute_insert($sql)) { $parent->last_error= "Failed to insert new version in the database\n"; return FALSE; } /* We retrieve the new release uniqueID */ $releases=query_version($TS_name, 1); if (!$releases) { $parent->last_error= "Internal error: the new version was not created\n"; return FALSE; } reset($releases); $rlstmp=current($releases); $release_id=$rlstmp["ver_id"]; /* We can create the full release description */ $release_description = array(); foreach ($NEW_TS as $routine => $rou_data) { if (!isset($current_routines[$routine]) || !isset($current_assertions[$routine])) { $parent->last_error= "Internal script error: routine $routine was not added in 1st pass"; return FALSE; } foreach ($rou_data["assertions"] as $assert_id => $assert_data) { foreach ($assert_data["tests"] as $test_number => $testname) { $release_description[]=array( "descr_assert" => array_search($assert_data["text"], $current_assertions[$routine]), "descr_num_assert" => $assert_data["number"], "descr_num_test" => $test_number, "descr_info" => $testname); } /* free some memory */ unset($rou_data["assertions"][$assert_id]); } } $counter=0; foreach ($release_description as $testcase) { $sql = "INSERT INTO opts_version_descriptions " ." (descr_version, descr_assert, descr_num_assert, descr_num_test, descr_info)" ." VALUES (".$release_id.", " .$testcase["descr_assert"].", " .$testcase["descr_num_assert"].", " .$testcase["descr_num_test"].", " .stringToDB($testcase["descr_info"])." )"; if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; if (db_execute_insert($sql)) $counter++; else echo "Failed to execute: ".htmlentities($sql)."\n"; } echo "<b><i>$counter testcases have been added</i></b>\n\n"; echo "Process terminated.\n"; return TRUE; } /* The next function is quite generic, but one may need additionnal cleanups. */ function TS_delete(&$parent, $TS_id) { if ( $parent->debug ) echo "newmodule->TS_delete($TS_id)\n"; /* Check there is no run within this testsuite */ $sql = "SELECT * from opts_run_results, opts_version_descriptions" ." WHERE res_testcase=descr_id" ." AND descr_version=".$TS_id; if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; $tmp = db_execute_select($sql); if ($tmp) { $parent->last_error="The testsuite contains runs -- cannot be deleted.\n Delete the runs first.\n"; return FALSE; } /* Check the testsuite is a newmodule one */ $sql = "SELECT ver_module from opts_versions" ." WHERE ver_id=".$TS_id; if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; $tmp = db_execute_select($sql); if (!$tmp) { $parent->last_error="The testsuite cannot be found in the database.\n"; return FALSE; } if ($tmp[0]["ver_module"] != "newmodule") @ /* @@@ Don't forget to change the module name here */ { $parent->last_error="The testsuite is not the right format -- cannot be deleted within the current module.\n"; return FALSE; } /* Now, delete the testsuite description */ $sql = "DELETE from opts_version_descriptions" ." WHERE descr_version=".$TS_id; if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; $tmp = db_execute_insert($sql); echo "$tmp rows deleted from opts_version_descriptions<br>\n"; /* and the testsuite name */ $sql = "DELETE from opts_versions" ." WHERE ver_id=".$TS_id; if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; $tmp = db_execute_insert($sql); if ($tmp == 0) { $parent->last_error="No row deleted in opts_version\n"; return FALSE; } if ($parent->debug > 1) echo "$tmp rows deleted from opts_version<br>\n"; return true; } /* The next function will parse a run log file and save the content to the database. The inputs are: $RUN_name and $RUN_description: information about the run being added. $TS_id: id (in database) of the release this runs belongs to. $CONTENT: This is a string containing the full content of the uploaded file. NOTE: if the uploaded results have a more complicated structure, you can access the raw file with $_FILES['logfile']['tmp_name'] -- see tahi module for example of a tar.gz result file. The outputs are: In the database, the following tables have new entries: opts_run, opts_run_results More precisely: opts_run has an entry added with the $RUN_name and $RUN_description values. opts_run_results has receives as many entries as the number of results in the logfile. Each entry references a testcase from opts_version_description. */ function RUN_parse(&$parent, $RUN_name, $RUN_description, $TS_id, $CONTENT) { if ( $parent->debug ) echo "newmodule->RUN_parse($RUN_name, $RUN_description, $TS_id, ...".strlen($CONTENT)."c...)\n"; /* Check this TS id first */ $sql = "SELECT ver_id, ver_name, ver_comment, ver_module FROM opts_versions WHERE ver_id=$TS_id"; if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; $release = db_execute_select($sql); if (!$release) { $parent->last_error="The provided testsuite ID was not found in database\n"; return false; } if ($release[0]["ver_module"] != "newmodule") @ /* @@@ Change the module name here */ { $parent->last_error="This testsuite's ID is not of the correct type. Aborted.\n"; return false; } /* Check that run name is free */ $sql = "SELECT run_id, run_name, run_comments FROM opts_run WHERE run_name LIKE ".stringToDB($RUN_name); if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; $res = db_execute_select($sql); if ($res) { $elem=$res[0]; $parent->last_error ="The test run '$RUN_name' is already in the database\n"; $parent->last_error.="<i>".stringFromDB($elem["run_comments"])."</i>\n"; return false; } /* * Now, parse the results. * Here is the 'intelligent' part of the work... * and no template can be provided... * The goal is to get an array of the results with the following format: $RESULTS = array( [descr_id] => array( "status" => [status of the corresponding testcase (i.e. PASSED, FAILED, ...)], "log" => [messages associated with this result] ) [descr_id] => ... * To get this, one may for example: -> parse the logfile with a perl regular expression => this gives a "flat" array of the results. -> then try and match every entry of the flat previous array to an entry into opts_version_description. the goal is to find the descr_id key corresponding to this result. we have: the TS_id identifier, and the test informations contained in the logfile (for example, this can be the filename, or the test number) You can refer to existing plug-ins for examples of different parsing methods. We consider that the $RESULTS array has been created for the rest of this function. */ echo "\n<b>".count($RESULTS)."</b> test results can be inserted in the results database.\n\n"; /* Now we've got to add the new run name in the database and get its ID */ $sql = "INSERT INTO opts_run ( run_name, run_comments )" ." VALUES ( ".stringToDB($RUN_name).", ".stringToDB($RUN_description)." )"; if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; $res = db_execute_insert($sql); if (!$res) { $parent->last_error="Failed to insert new run name"; return false; } $sql = "SELECT run_id, run_name, run_comments FROM opts_run WHERE run_name LIKE ".stringToDB($RUN_name); if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; $res = db_execute_select($sql); if (!$res) { $parent->last_error="Internal error: the run was inserted but disappeared\n"; return false; } $run_id=$res[0]["run_id"]; /* Add the results now */ $counter=0; foreach($RESULTS as $desc_id => $testdata) { $sql = "INSERT INTO opts_run_results ( res_run, res_testcase, res_status, res_log )" ." VALUES ( $run_id, $desc_id, ".stringToDB($testdata["status"]).", " .stringToDB($testdata["log"])." )"; if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; if (db_execute_insert($sql)) $counter++; else echo "<b><i>Failed to execute the following instruction</i></b>; skipping.\n$sql\n"; } echo "<b>$counter</b> records added to the database!\n"; return true; } /* The next function is quite generic, but one may need additional cleanups */ function RUN_delete(&$parent, $RUN_id) { if ( $parent->debug ) echo "newmodule->RUN_delete($RUN_id)\n"; /* Check this run belongs to an newmodule testsuite */ $sql = "SELECT ver_module FROM opts_versions, opts_version_descriptions, opts_run_results" ." WHERE res_run=$RUN_id" ." AND res_testcase=descr_id AND descr_version=ver_id" ." GROUP BY ver_module"; if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; $tmp = db_execute_select($sql); if (!$tmp) { $parent->last_error="The run ID or corresponding testsuite cannot be found in the database.\n"; return FALSE; } if ($tmp[0]["ver_module"] != "newmodule") @ /* @@@ change the name here */ { $parent->last_error="The testsuite is not of the correct format -- cannot be deleted within the current module.\n"; return FALSE; } /* We can delete everything related to this run */ $sql = "DELETE from opts_run_results " ."WHERE res_run=$RUN_id"; if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; $tmp = db_execute_insert($sql); if ($tmp == 0) { $parent->last_error="No row deleted in opts_run_results\n"; return FALSE; } echo "$tmp rows deleted from opts_run_results<br>\n"; $sql = "DELETE from opts_run " ."WHERE run_id=$RUN_id"; if ($parent->debug > 1) echo htmlentities($sql)."<br>\n"; $tmp = db_execute_insert($sql); if ($tmp == 0) { $parent->last_error="No row deleted in opts_run\n"; return FALSE; } echo "$tmp row deleted from opts_run<br>\n"; return true; } } /* Return the class name so it is added to the catalog */ return("newmodule"); ?> |