Location: PHPKode > projects > Test Suites Results Parser and Browser > tslogparser-v07/admin/modules/tahi.mod.php
<?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 is for use with the TAHI Conformance Test Suite.
 	See the module informations (module_info) for limitations.
 */
 
 
 /* Here is a bit of design, for integration purpose.
 This is needed because the OPTS and TAHI do not have an exact same structure.
 Here is the mapping for information between TAHI and tslogparser database.
 
 -------------------- TAHI Test Suite description -----------------------
 
 The testsuite description is extracted from the INDEX file. Also, the *.seq files
 are used. Here is the description of the process:
 
 The INDEX file has the following format:
 
 #, // starting lines are comments and are ignored.
 
 &print: lines are test categories, and are mapped to tslogparser routines concept.
 
 ./CN-1-1.seq: lines are test cases, and are mapped to tslogparser assertions concept.
 
 
 As an example here is a sample entry of a TAHI testsuite description:
 
 === Table opts_routines
  rou_id     : 198
  rou_name   : 2.2
  rou_comment: Processing Mobility Headers -- Receiving CoTI
  
 === Table opts_assertions
  assert_id      : 1466
  assert_routine : 198
  asser_text     : (here goes the full content of file CN-1-1.seq)
  
 Note: the CN-1-1.seq file contains the full description of the test, 
 when available.
 
 === Table opts_versions
  ver_id      : 4
  ver_name    : ct-mipv6-cn-3.1.2
  ver_comment : IPv6 Mobility TAHI Test Suite for Correspondant Node functions + URL
  ver_module  : tahi
  
 === Table opts_version_descriptions
  descr_id        : 6435
  descr_version   : 4
  descr_assert    : 1466
  descr_num_asser : 1
  descr_num_test  : 1
  descr_info      : ./CN-1-1.seq
  
 Note: descr_num_assert is not usefull for this module - we put dummy values.
 
 descr_num_test is obtained from the INDEX file (# of test)
 
 
 === Table opts_run
  run_id      : 20
  run_name    : Mipl2-rc2 without IPsec
  run comment : configuration file available at http://...
  
 === Table opts_run_results
  res_run      : 20
  res_testcase : 6435
  res_status   : PASS
  res_log      : (contenu du fichier 1.html)
 
 
 */

 
/* The following function parses the file $root/$ts_type/INDEX and saves the
  result into $tahi_tree. It returns TRUE on success and FALSE on failure. */
function parse_INDEX(&$tahi_tree, $root, $ts_type, $debug)
{
	/* The format of $tahi_tree is as follows: 
	
	$tahi_tree=array(
		"mipv6-mn-0" => array(
			"name"  => "Basic Sequence"
			"tests" => array(
				1 => array(
					"filename" => "./MN-0-0-0-1-001.seq"
					"testname" => "MN-0-0-0-1-001 - Mobile Node Operation-1"
					"content" => (file content)
					)
				2 => array(
					"filename" => ...
					)
				)
			)
		"mipv6-mn-14/4" => array(
			"name"  => "Mobile to Mobile / Binding Error"
			"tests" => array(
				116 => ...
				)
			
	
	*/
	
	
	if ($debug)
		echo "parse_INDEX($root/$ts_type)\n";
	
	/* Read the file */
	$fichier = file("$root/$ts_type/INDEX");
	
	$cur_hierarchy = $ts_type;
	$cur_level = 0;
	$tab_hierarchy=array();
	$counter = 0;
	
	/* Browse the file content */
	foreach ($fichier as $ligne)
	{
		/* Strip empty lines */
		if (!($ligne = trim($ligne)))
			continue;
		
		/* Strip comments -- files starting with # or // as their first non-blank characters */
		if (preg_match("/^(#|\/\/)/", $ligne))
			continue;
		
		$match = FALSE;
		//if ($debug)
		//	echo htmlentities($ligne)."\n";
		
		/* The format should be either
		  &print:<B>(test category hierarchy)</B>
		   or
		  (file):(anything):(anything):(anything):(test name):(anything)
		*/
		$regs=array();
		if (preg_match("/^&print:\s*<B>(.*)\<\/B>$/", $ligne, $regs))
		{
			$match = TRUE;
			$hierarchy = str_replace("&nbsp;", " ", trim(strip_tags($regs[1])));
			//if ($debug)
			//	echo "Hierarchy: ".htmlentities($hierarchy)."\n";
			
			/* We are looking for hierarchical information:
			  n. <blablah> => level 1
			  n.m. <blablah> => level 2
			  (n) <blabla> => sublevel
			*/
			if (preg_match("/^(\d+)\.\s(.*)$/", $hierarchy,$regs))
			{
				$cur_level=$regs[1];
				$cur_hierarchy=$regs[2];
				$tab_hierarchy[$cur_level]=$cur_hierarchy;
			}
			if (preg_match("/^(\d+)\.(\d+)\.\s(.*)$/", $hierarchy,$regs))
			{
				$cur_level=$regs[1].".".$regs[2];
				$cur_hierarchy=$tab_hierarchy[$regs[1]]." -- ".$regs[3];
				$tab_hierarchy[$cur_level]=$cur_hierarchy;
			}
			$tmp_level = $cur_level;
			$tmp_hierarchy=$cur_hierarchy;
			
			if (preg_match("/^\((\d+)\)\s(.*)$/", $hierarchy,$regs))
			{
				$tmp_level=$cur_level."/".$regs[1];
				$tmp_hierarchy=$cur_hierarchy." / ".$regs[2];
			}
			
		}
		
		if (preg_match("/^(?:&#)?([^:]+):[^:]*:[^:]*:[^:]*:([^:]+)(:.*)?$/",$ligne,$regs))
		{
			$match = TRUE;
			//if ($debug)
			//	echo "Test info: ".htmlentities($regs[1]." => ".$regs[2])."\n";
			
			$counter++;
			
			if (!isset($tahi_tree[$ts_type."-".$tmp_level]))
				$tahi_tree[$ts_type."-".$tmp_level]=array(
					"name" => $tmp_hierarchy,
					"tests" => array()
					);
			
			$tahi_tree[$ts_type."-".$tmp_level]["tests"][$counter]=array(
				"filename" => $regs[1],
				"testname" => $regs[2],
				"content" => file_get_contents("$root/$ts_type/".$regs[1])
				);
			
		}
		
		if (!$match)
			echo "Ignored the following line: ".htmlentities($ligne)."\n";
	}
	
//	if ($debug)
//		print_r($tahi_tree);
	
	return TRUE;
}


class tahi {
/*
 module_info will return an HTML-formated text (enclosed in <p> and </p> tags)
  describing the module and the testsuite it supports.
  All information related to the module (version, known bugs, ...) are suitable 
  for this function (think of it as the only documentation for the module).
*/
	function module_info($what="")
	{
		$title = "<b>TAHI Conformance Test Suite</b> parser module for <b>TSLogParser</b>";

		$text = "<p>$title</p>\n";
		$text.= "<p>Release: <b>1.0</b> 2005/07/05</p>\n";
		$text.= "<p>Limitations and known problems: \n";
		$text.= "<ul>\n";
		$text.=      "<li>One may need to increase the <b>upload_max_filesize</b>";
		$text.=             " and <b>post_max_size</b> values in /etc/php.ini.\n";
		$text.=      "<li>For the HA tests, the TS archive cannot be parsed directly, ";
		$text.=             "one need to build the INDEX file previously to uploading.\n ";
		$text.=      "<li>Tested with :<ul>\n";
		$text.=            "<li>ct-mipv6-cn-3.1.2.tar.gz ct-mipv6-cn-3.1.5.tar.gz\n";
		$text.=            "<li>ct-mipv6-ha-3.1.2.tar.gz, ct-mipv6-ha-3.1.4.tar.gz\n";
		$text.=            "<li>ct-mipv6-mn-3.1.1.tar.gz, t-mipv6-mn-3.1.4.tar.gz</ul>\n";
		$text.= "</ul></p>\n";
		$text.= "<p>See the <a href='http://www.tahi.org/mipv6/index.html'>test suite homepage</a> for more information.</p>\n";
		
		if ($what == "title")
			return $title;

		/* default to all */
		return $text;
	}
	
/*	
 TS_parse will check for the directory TS_path and analyse its content.
  In case a correct testsuite structure is found, the testsuite is parsed
  and put into the database with name and description as provided.
  The return value is $true if success and $false otherwise.
*/	
	function TS_parse(&$parent, $TS_name, $TS_description, $path)
	{
		if ( $parent->debug )
			echo "tahi->TS_parse($TS_name, $TS_description, $path)\n";
		
		$tahi_tree=array();
		$found=FALSE;
		
		/* Check the directory contains a coherent structure 
		    We are looking for a file something/INDEX -- and are interested
		    in this something :) 
		    
		    We browse each subdirectory until we find the file we
		    are looking for...
		*/

		if (!is_dir($path) || !($dh  = opendir($path)))
		{
			$parent->last_error="Directory '$path' is not readable -- check your archive format.\n";
			return FALSE;
		}
		
		while (($file = readdir($dh)) !== false) 
		{
			if (($file == ".") || ($file == "..") || ($file == "CVS") || !is_dir($path."/".$file))
				continue;
		
			$dh2 =  opendir($path."/".$file);
			if (!$dh2)
			{
				$parent->last_error= "Failed to open directory $path/$file for reading.\n";
				return FALSE;
			}
			
			while (($file2 = readdir($dh2)) !== false) 
			{
				if ($file2 != "INDEX") 
					continue;
				
				$found = TRUE;
				
				/* Now we found the file we were looking for: $path/$file/INDEX */
				if (! parse_INDEX($tahi_tree, $path, $file, $parent->debug))
				{
					$parent->last_error= "Parsing of INDEX failed\n";
					return FALSE;
				}
			}
			closedir ($dh2);
		}
		closedir($dh);
		
		if (!$found)
		{
			$parent->last_error="Directory '$path' does not contain a file */INDEX -- unable to parse.\n";
			return FALSE;
		}
		
		
		/* We've parsed the whole tree */
		if ($parent->debug > 2)
			print_r($tahi_tree);
		
		/* 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 exist */
		$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;
		}
		
		/* Now, compare the $tahi_tree with the $current_tests and build up the list of tests
		   to be added to the database.*/
		   
		   
		$current_categories=query_routines();
		
		/* We start with looking for missing routines */
		$missing_category=array();

		/* browse the new release assertions */
		foreach ($tahi_tree as $category=>$data)
		{
			/* If the category is missing from opts_routines table, we'll add it */
			if (!isset($current_categories[$category]))
				$missing_category[]=$category;
			else /* check the category was not renumbered from the previous entered version */
				if ($data["name"] != $current_categories[$category]["routine_comment"])
				{
					echo "Inconsistency found for category <b>$category</b><br>\n";
					echo "Old name: ".$current_categories[$category]["routine_comment"]."<br>\n";
					echo "New name: ".$data["name"]."\n";
					
					$parent->last_error= "Unable to add $category to the database\n";
					return FALSE;
				}
					
		}
		
		if ($parent->debug > 1)
			print_r($missing_category);
		
		/* If any category is missing, it must be added previously to further processing */
		if ($missing_category)
		{
			echo "New categories of tests are being added to the database...\n";
			$counter=0;
			foreach ($missing_category as $cat)
			{
				$sql = "INSERT INTO opts_routines ( rou_name, rou_comment ) "
					."VALUES ( ".stringToDB($cat).","
					.stringToDB($tahi_tree[$cat]["name"])." )";
				if ($parent->debug > 1)
					echo htmlentities($sql)."<br>\n";
				if (db_execute_insert($sql))
					$counter++;
				else
					echo "Failed to add $cat to the database...\n";
			}
			echo "Done. <b>$counter</b> categories have been added.\n\n";
			$current_categories=query_routines();
		}
		
		/* Now we are adding new tests if any */
		
		$current_tests=query_all_asserts();
		$missing_tests=array();
		
		/* Check for existing tests */
		foreach ($tahi_tree as $cat => $cat_data)
		{
			if (!isset($current_tests[$cat]))
			{
				if (!isset($current_categories[$cat]))
				{
					$parent->last_error="Internal script error: category $cat was not added in 1st pass";
					return FALSE;
				}
				
				/* We now schedule addition of these tests for this category, as none was already defined */
				foreach ($cat_data["tests"] as $test_data)
				{
					$missing_tests[]=array(
						"cat"=>$cat,
						"name"=>$test_data["testname"],
						"file"=>$test_data["filename"],
						"content"=>&$test_data["content"]);
				}
			}
			else /* some tests were already defined in this category */
			{
				foreach ($cat_data["tests"] as $test_data)
				{
					/* Check if this test content was already in the database */
					if(!in_array($test_data["content"], $current_tests[$cat]))
						$missing_tests[]=array(
							"cat"=>$cat,
							"name"=>$test_data["testname"],
							"file"=>$test_data["filename"],
							"content"=>&$test_data["content"]
							);
				}
			}
		}
		if ($parent->debug > 1)
			print_r($missing_tests);
				
		/* If any assertion is missing, it must be added previously to further processing */
		if ($missing_tests)
		{
			echo "New tests are being added to the database...\n";
			$counter=0;
			foreach ($missing_tests as $test)
			{
				$sql = "INSERT INTO opts_assertions ( assert_routine, assert_text ) "
					."VALUES ( ".$current_categories[$test["cat"]]["routine_id"].","
					.stringToDB($test["content"])." )";
				if ($parent->debug > 1)
					echo htmlentities($sql)."<br>\n";
				if (db_execute_insert($sql))
					$counter++;
				else
					echo "Failed to add test ".$test["testname"]." (".$test["filename"].") to the database...\n";
			}
			echo "Done. <b>$counter</b> tests have been added.\n\n";
			$current_tests=query_all_asserts();
		}
		
	
		/* OK, we can now create the new release of TAHI in the database */
		$sql="INSERT INTO opts_versions (ver_name, ver_comment, ver_module) "
			. "VALUES ( ".stringToDB($TS_name).", "
			. stringToDB($TS_description).", "
			. "'tahi' )";
		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 TAHI version was not created\n";
			return FALSE;
		}
		if ($parent->debug > 2)
			print_r($current_tests);
		
		/* We can create the full release description */
		$release_description = array();
		foreach ($tahi_tree as $cat => $cat_data)
		{
			if (!isset($current_tests[$cat]) || !isset($current_categories[$cat]))
			{
				$parent->last_error= "Internal script error: category $cat was not added in 1st pass";
				return FALSE;
			}
			
			foreach ($cat_data["tests"] as $test_nr => $test_data)
			{
				$release_description[]=array(
					"descr_assert" => array_search($test_data["content"], $current_tests[$cat]),
					"descr_num_test" => $test_nr,
					"descr_info" => $test_data["filename"]);
			}
		}
		
		/* We've enough information now; we can create the release */
		reset($releases);
		$rlstmp=current($releases);
		$release_id=$rlstmp["ver_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"].", "
					    ."0, "
					    .$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;
	}
	
	
	function TS_delete(&$parent, $TS_id)
	{
		
		if ( $parent->debug )
			echo "tahi->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 TAHI 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"] != "tahi")
		{
			$parent->last_error="The testsuite is not TAHI -- 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;
	}
	
	
	function RUN_parse(&$parent, $RUN_name, $RUN_description, $TS_id, &$CONTENT)
	{
		if ( $parent->debug )
			echo "tahi->RUN_parse($RUN_name, $RUN_description, $TS_id, ...".strlen($CONTENT)."c...)\n";
			
		/* We won't need the CONTENT var here -- we free some memory */
		unset($CONTENT);
		
		/* 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"] != "tahi")
		{
			$parent->last_error="This testsuite's ID is not of type TAHI Conformance Test Suite. 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;
		}
		
		/* Parse the results files -- which shall be a tar.gz file.
			-> uncompress the file into a temp directory
			-> look for the results
			-> parse these results
		*/
		
		/* Set a longer execution time */
		set_time_limit(60);
		
		/* This is quite dirty... we simply ignore the CONTENT string. */
		$tar = new Archive_Tar($_FILES['logfile']['tmp_name']);
		$tar->setErrorHandling(PEAR_ERROR_PRINT);
		
		$tmpdir = "../ts/".time();
		
		if (!$tar->extractModify($tmpdir, ""))
		{
			$parent->last_error ="Archive extraction failed. Please provide the results as a 'tar.gz' file.\n";
			return false;
		}
		
		/* Find directory name from inside archive, if any */
		/* 1 - check the files are inside a subdirectory */
		if (!is_file($tmpdir."/report.html"))
		{
			/* 2 - open the directory where files were extracted */
			if ($dh = opendir($tmpdir)) 
			{
				/* 3 - list the files. We assume there is only 1 directory here */
				while (($file = readdir($dh)) !== false) 
				{
					if (($file == ".") || ($file == ".."))
						continue;
					if (is_dir($tmpdir."/".$file))
					{
						$tmpdir .= "/".$file;
						break;
					}
					$parent->last_error ="Unexpected entry in archive: $file";
					return false;
				}
				/* 4 - close the directory */
				closedir($dh);
			}
			else
			{
				$parent->last_error = "Unable to open temporary directory $tmpdir";
				return FALSE;
			}
		}
		
		if (!is_file($tmpdir."/report.html"))
		{
			$parent->last_error = "Unable to find 'report.html' file in uploaded results.";
			return FALSE;
		}
		
		$log = file($tmpdir."/report.html");
		if (!$log)
		{
			$parent->last_error = "Unable to read '$tmpdir/report.html' file.";
			return FALSE;
		}
		
		/* Example of a tests status:
		<TD>7</TD><TD><A HREF="./MN-3-3-1-1-003.html">MN-3-3-1-1-003 - Use Neighbor Unreachability Detection (Target Address=global)</A></TD><TD ALIGN="CENTER">PASS</TD><TD ALIGN="CENTER"><A HREF="7.html">X</A></TD><TD ALIGN="CENTER"><A HREF="./MN-3-3-1-1-003.seq">X</A></TD><TD ALIGN="CENTER"><A HREF="./mip6_mn_common.def">X</A></TD><TD ALIGN="CENTER"><A HREF="7.html.Link0.dump">Link0</A> </TD></TR>
		<TD>4</TD><TD>CN-2-1-1 - Receiving HoTI - Invalid Mobility Option (Nonce Indices option)</TD><TD ALIGN="CENTER">PASS</TD><TD ALIGN="CENTER"><A HREF="4.html">X</A></TD><TD ALIGN="CENTER"><A HREF="./CN-2-1-1.seq">X</A></TD><TD ALIGN="CENTER"><A HREF="./mip6cnt.def">X</A></TD><TD ALIGN="CENTER"><A HREF="4.html.Link0.dump">Link0</A> </TD></TR>


		What we try and match is:
		<TD>(param1)</TD><TD><A HREF="(*)">(param2)</A></TD><TD ALIGN="CENTER">(param3)</TD><TD ALIGN="CENTER"><A HREF="(param4)">X</A></TD><TD ALIGN="CENTER"><A HREF="(param5)">X</A></TD><TD ALIGN="CENTER">(*)</TD><TD ALIGN="CENTER">(*)</TD></TR>
		where:
		   param1: # of the test (format: numeric)
		   param2: Name of the test.
		   param3: Status
		   param4: log file
		   param5: filename of the testcase
		*/
		$test_results=array();
		
		$regex = "/^<TD>"
			."(\d+)" 	// param1
			."<\/TD>"
			."<TD>(?:<A HREF=\"[^\"]*\">)?"
			."(.*?)" 	// param2
			."(?:<\/A>)?<\/TD>"
			."<TD ALIGN=\"CENTER\">"
			."(.*?)" 	// param3
			."<\/TD>"
			."<TD ALIGN=\"CENTER\"><A HREF=\""
			."(.*?)" 	// param4
			."\">X<\/A><\/TD>"
			."<TD ALIGN=\"CENTER\"><A HREF=\""
			."(.*?)"	// param5
			."\">X<\/A><\/TD>"
			."<TD ALIGN=\"CENTER\">.*?<\/TD>"
			."<TD ALIGN=\"CENTER\">.*?<\/TD>"
			."<\/TR>$/";
		
		foreach ($log as $nr => $ligne)
		{
			/* Line parsing */
			if (preg_match($regex, $ligne, $regs))
			{
				$test_results[$regs[1]]=array(
					"name" => trim($regs[2]),
					"status" => trim(strip_tags($regs[3])),
					"log" => $tmpdir."/".$regs[4],
					"filename" => trim($regs[5])
					);
			}
			else
			{
				if ($parent->debug)
					echo "Discarded: ".htmlentities($ligne)."\n";
			}
		}
		
		/* We also need the release description from the database */
		$sql = "SELECT descr_id, descr_num_test, descr_info"
			." FROM opts_version_descriptions"
			." WHERE descr_version=$TS_id";
		if ($parent->debug > 1)
			echo htmlentities($sql)."<br>\n";		
		$version_description = db_execute_select($sql);
		if (!$version_description)
		{
			$parent->last_error="The TAHI release description was not found in database.\n";
			return false;
		}
		
		/* We're ready to proceed:
		 * -> walk through the release description
		 * -> foreach test, find the corresponding result
		 * -> save a record with the information: description ID, test status, test log.
		 * -> this will then be used to generate the database entries.
		 */
		
		$parsed_results=array();
		$missing_results=array();
		foreach ($version_description as $record)
		{
			if (!isset($test_results[$record["descr_num_test"]]))
			{
				$missing_results[]=$record["descr_num_test"];
				continue;
			}
			if ($test_results[$record["descr_num_test"]]["filename"] != $record["descr_info"])
			{
				echo "Test ".$record["descr_num_test"]." does not match database description ("
					.$test_results[$record["descr_num_test"]]["filename"]." != " . $record["descr_info"].".\n"
					."Result ignored";
				continue;
			}
			/* Ok we found a corrsponding entry */
			$parsed_results[]=array(
				"res_testcase" => $record["descr_id"],
				"res_status"   => $test_results[$record["descr_num_test"]]["status"],
				"res_log"      => $test_results[$record["descr_num_test"]]["log"]
				);
			
			/* remove this test result */
			unset($test_results[$record["descr_num_test"]]);
		}
		
		if ($missing_results)
		{
			echo count($missing_results)." tests are missing from analyzed logfile.\n";
			if ($parent->debug)
			{
				echo "Missing tests results:\n";
				print_r($missing_results);
			}
		}
		unset ($missing_results);
		
		if ($test_results)
		{
			echo count($test_results)." tests are missing from release description in database.\n";
			if ($parent->debug)
			{
				echo "Missing tests description:\n";
				print_r($test_results);
			}
		}
		
		unset($test_results);
		
		
		/* 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 records in opts_run_results */
		$count=0;
		foreach ($parsed_results as $entry)
		{
			$sql = "INSERT INTO opts_run_results "
				."(res_run, res_testcase, res_status, res_log) "
				." VALUES ("
				.$run_id.", "
				.$entry["res_testcase"].", "
				.stringToDB($entry["res_status"]).", "
				.stringToDB(html_entity_decode(file_get_contents($entry["res_log"]))).")";
			if ($parent->debug > 1)
				echo htmlentities($sql)."<br>\n";		
			$res = db_execute_insert($sql);
			if (!$res)
				echo "Failed to add record for test ".$entry["res_testcase"]."\n";
			else
				$count++;
		}
		echo "$count results were inserted in the database.\n";
		
		/* Delete the extracted tarball */
		function deldir($dir) {
		   $dh=opendir($dir);
		   while ($file=readdir($dh)) {
		       if($file!="." && $file!="..") {
			   $fullpath=$dir."/".$file;
			   if(!is_dir($fullpath)) {
			       unlink($fullpath);
			   } else {
			       deldir($fullpath);
			   }
		       }
		   }
		   closedir($dh);
		   rmdir($dir);
		}
		
		deldir($tmpdir);
		
		return true;
	}
	
	
	function RUN_delete(&$parent, $RUN_id)
	{
		if ( $parent->debug )
			echo "tahi->RUN_delete($RUN_id)\n";
		
		/* Check this run belongs to an OPTS 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"] != "tahi")
		{
			$parent->last_error="The testsuite is not TAHI -- 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("tahi");
?>
Return current item: Test Suites Results Parser and Browser