Started to put metadata into the files table.

Gave the table sequences their own config values in $CC_CONFIG.
This allows us to change their names from one single place.

Fixed WHITE_SCREEN_OF_DEATH warnings.

Added PHPUnit to the pear library.

Started adding unit tests in storageServer/var/tests.
This commit is contained in:
paul.baranowski 2010-09-14 10:18:53 -04:00
parent e537255e27
commit 7ea2352ca3
33 changed files with 4423 additions and 366 deletions

View File

@ -25,3 +25,36 @@ DROP TABLE as_cmemb CASCADE;
DROP SEQUENCE as_struct_id_seq_seq; DROP SEQUENCE as_struct_id_seq_seq;
DROP SEQUENCE as_tree_id_seq_seq; DROP SEQUENCE as_tree_id_seq_seq;
ALTER TABLE cc_files
ADD COLUMN track_title character varying(512);
ALTER TABLE cc_files
ADD COLUMN artist_name character varying(512);
ALTER TABLE cc_files
ADD COLUMN bit_rate character varying(32);
ALTER TABLE cc_files
ADD COLUMN sample_rate character varying(32);
ALTER TABLE cc_files
ADD COLUMN format character varying(128);
ALTER TABLE cc_files
ADD COLUMN length character (16);
ALTER TABLE cc_files
ADD COLUMN album_title character varying(512);
ALTER TABLE cc_files
ADD COLUMN genre character varying(64);
ALTER TABLE cc_files
ADD COLUMN comments text;
ALTER TABLE cc_files
ADD COLUMN "year" character varying(16);
ALTER TABLE cc_files
ADD COLUMN track_number integer;
ALTER TABLE cc_files
ADD COLUMN channels integer;
ALTER TABLE cc_files
ADD COLUMN url character varying(1024);

View File

@ -128,7 +128,7 @@ class Alib {
public static function AddPerm($sid, $action, $oid, $type='A') public static function AddPerm($sid, $action, $oid, $type='A')
{ {
global $CC_CONFIG, $CC_DBC; global $CC_CONFIG, $CC_DBC;
$permid = $CC_DBC->nextId($CC_CONFIG['permTable']."_id_seq"); $permid = $CC_DBC->nextId($CC_CONFIG['permSequence']);
$sql = "INSERT INTO ".$CC_CONFIG['permTable']." (permid, subj, action, obj, type)" $sql = "INSERT INTO ".$CC_CONFIG['permTable']." (permid, subj, action, obj, type)"
." VALUES ($permid, $sid, '$action', $oid, '$type')"; ." VALUES ($permid, $sid, '$action', $oid, '$type')";
$r = $CC_DBC->query($sql); $r = $CC_DBC->query($sql);

View File

@ -37,7 +37,7 @@ class Subjects {
if (!$p_login) { if (!$p_login) {
return $CC_DBC->raiseError("Subjects::AddSubj: empty login"); return $CC_DBC->raiseError("Subjects::AddSubj: empty login");
} }
$id = $CC_DBC->nextId($CC_CONFIG['subjTable']."_id_seq"); $id = $CC_DBC->nextId($CC_CONFIG['subjSequence']);
if (PEAR::isError($id)) { if (PEAR::isError($id)) {
return $id; return $id;
} }
@ -441,7 +441,7 @@ class Subjects {
} }
} }
} else { } else {
$id = $CC_DBC->nextId($CC_CONFIG['smembTable']."_id_seq"); $id = $CC_DBC->nextId($CC_CONFIG['smembSequence']);
if (PEAR::isError($id)) { if (PEAR::isError($id)) {
return $id; return $id;
} }

View File

@ -20,6 +20,22 @@ require_once(dirname(__FILE__)."/../../alib/var/Alib.php");
require_once("StoredFile.php"); require_once("StoredFile.php");
require_once("Transport.php"); require_once("Transport.php");
$g_metadata_xml_to_db_mapping = array(
'dc:format' => "format",
"ls:bitrate" => "bit_rate",
"ls:samplerate" => "sample_rate",
"dcterms:extent" => "length",
"dc:title" => "track_title",
"dc:description" => "comments",
"dc:type" => "genre",
"dc:creator" => "artist_name",
"dc:source" => "album_title",
"ls:channels" => "channels",
"ls:filename" => "name",
"ls:year" => "year",
"ls:url" => "url",
"ls:track_num" => "track_number");
/** /**
* Core of Campcaster file storage module * Core of Campcaster file storage module
* *
@ -683,10 +699,11 @@ class BasicStor {
if (is_null($storedFile) || PEAR::isError($storedFile)) { if (is_null($storedFile) || PEAR::isError($storedFile)) {
return $storedFile; return $storedFile;
} }
$r = $storedFile->md->getMetadataValue('dc:title', $lang, $deflang); // $r = $storedFile->md->getMetadataValue('dc:title', $lang, $deflang);
if (PEAR::isError($r)) { // if (PEAR::isError($r)) {
return $r; // return $r;
} // }
$r = $storedFile->md["title"];
$title = (isset($r[0]['value']) ? $r[0]['value'] : 'unknown'); $title = (isset($r[0]['value']) ? $r[0]['value'] : 'unknown');
return $title; return $title;
} }
@ -741,24 +758,42 @@ class BasicStor {
return $storedFile; return $storedFile;
} }
if (is_null($category)) { if (is_null($category)) {
return $storedFile->md->getAllMetadata(); return $storedFile->md;
} elseif (is_array($category)) { } elseif (is_array($category)) {
$values = array(); $values = array();
foreach ($category as $tmpCat) { foreach ($category as $tmpCat) {
$values[$tmpCat] = $storedFile->md->getMetadataValue($tmpCat); // $values[$tmpCat] = $storedFile->md->getMetadataValue($tmpCat);
} $values[$tmpCat] = $storedFile->md[$tmpCat];
return $values; }
return $values;
} else { } else {
return $storedFile->md->getMetadataValue($category); // return $storedFile->md->getMetadataValue($category);
return $storedFile->md[$category];
} }
} }
public static function xmlCategoryToDbColumn($p_category)
{
global $g_metadata_xml_to_db_mapping;
if (array_key_exists($p_category, $g_metadata_xml_to_db_mapping)) {
return $g_metadata_xml_to_db_mapping[$p_category];
}
return null;
}
public static function dbColumnToXmlCatagory($p_dbColumn)
{
global $g_metadata_xml_to_db_mapping;
return array_search($p_dbColumn, $g_metadata_xml_to_db_mapping);
}
/** /**
* Set metadata element value * Set metadata element value
* *
* @param int|StoredFile $id * @param int|StoredFile $id
* Virtual file's local id * Database ID of file
* @param string $category * @param string $category
* Metadata element identification (e.g. dc:title) * Metadata element identification (e.g. dc:title)
* @param string $value * @param string $value
@ -773,34 +808,45 @@ class BasicStor {
* flag, if true, regenerate XML file * flag, if true, regenerate XML file
* @return boolean * @return boolean
*/ */
public function bsSetMetadataValue($id, $category, $value, public static function bsSetMetadataValue($p_id, $p_category, $p_value)/*,
$lang=NULL, $mid=NULL, $container='metadata', $regen=TRUE) $lang=NULL, $mid=NULL, $container='metadata', $regen=TRUE)*/
{ {
if (!is_string($category) || is_array($value)) { global $CC_CONFIG, $CC_DBC;
if (!is_string($p_category) || is_array($p_value)) {
return FALSE; return FALSE;
} }
if (is_a($id, "StoredFile")) { if (is_a($p_id, "StoredFile")) {
$storedFile =& $id; $storedFile =& $p_id;
} else { } else {
$storedFile = StoredFile::Recall($id); $storedFile = StoredFile::Recall($p_id);
if (is_null($storedFile) || PEAR::isError($storedFile)) { if (is_null($storedFile) || PEAR::isError($storedFile)) {
return $storedFile; return $storedFile;
} }
} }
if ($category == 'dcterms:extent') { if ($p_category == 'dcterms:extent') {
$value = BasicStor::NormalizeExtent($value); $p_value = BasicStor::NormalizeExtent($p_value);
} }
$res = $storedFile->md->setMetadataValue($category, $value, $lang, $mid, $container); $columnName = BasicStor::xmlCategoryToDbColumn($p_category); // Get column name
if (PEAR::isError($res)) {
return $res; if (!is_null($columnName)) {
} $escapedValue = pg_escape_string($p_value);
if ($regen) { $sql = "UPDATE ".$CC_CONFIG["filesTable"]
$r = $storedFile->md->regenerateXmlFile(); ." SET $columnName='$escapedValue'"
if (PEAR::isError($r)) { ." WHERE id=".$storedFile->getId();
return $r; //var_dump($sql);
//$res = $storedFile->md->setMetadataValue($category, $value, $lang, $mid, $container);
$res = $CC_DBC->query($sql);
if (PEAR::isError($res)) {
return $res;
} }
} }
return $res; // if ($regen) {
// $r = $storedFile->md->regenerateXmlFile();
// if (PEAR::isError($r)) {
// return $r;
// }
// }
// return $res;
} }
@ -826,8 +872,8 @@ class BasicStor {
/** /**
* Set metadata values in 'batch' mode * Set metadata values in 'batch' mode
* *
* @param int $id * @param int|StoredFile $id
* Virtual file's local ID * Database ID of file or StoredFile object
* @param array $values * @param array $values
* array of key/value pairs * array of key/value pairs
* (e.g. 'dc:title'=>'New title') * (e.g. 'dc:title'=>'New title')
@ -839,33 +885,37 @@ class BasicStor {
* flag, if true, regenerate XML file * flag, if true, regenerate XML file
* @return boolean * @return boolean
*/ */
public function bsSetMetadataBatch( public static function bsSetMetadataBatch(
$id, $values, $lang=NULL, $container='metadata', $regen=TRUE) $id, $values, $lang=NULL, $container='metadata', $regen=TRUE)
{ {
if (!is_array($values)) { if (!is_array($values)) {
$values = array($values); $values = array($values);
} }
$storedFile = StoredFile::Recall($id); if (is_a($id, "StoredFile")) {
if (is_null($storedFile) || PEAR::isError($storedFile)) { $storedFile =& $id;
return $storedFile; } else {
}
foreach ($values as $category => $oneValue) {
$res = $this->bsSetMetadataValue($storedFile, $category,
$oneValue, $lang, NULL, $container, FALSE);
if (PEAR::isError($res)) {
return $res;
}
}
if ($regen) {
$storedFile = StoredFile::Recall($id); $storedFile = StoredFile::Recall($id);
if (is_null($storedFile) || PEAR::isError($storedFile)) { if (is_null($storedFile) || PEAR::isError($storedFile)) {
return $storedFile; return $storedFile;
} }
$r = $storedFile->md->regenerateXmlFile(); }
if (PEAR::isError($r)) { foreach ($values as $category => $oneValue) {
return $r; $res = BasicStor::bsSetMetadataValue($storedFile, $category,
$oneValue/*, $lang, NULL, $container, FALSE*/);
if (PEAR::isError($res)) {
return $res;
} }
} }
// if ($regen) {
// $storedFile = StoredFile::Recall($id);
// if (is_null($storedFile) || PEAR::isError($storedFile)) {
// return $storedFile;
// }
// $r = $storedFile->md->regenerateXmlFile();
// if (PEAR::isError($r)) {
// return $r;
// }
// }
return TRUE; return TRUE;
} }
@ -1015,7 +1065,8 @@ class BasicStor {
if (is_null($storedFile) || PEAR::isError($storedFile)) { if (is_null($storedFile) || PEAR::isError($storedFile)) {
return $storedFile; return $storedFile;
} }
$MDfname = $storedFile->md->getFileName(); // $MDfname = $storedFile->md->getFileName();
$MDfname = $storedFile->md["name"];
if (PEAR::isError($MDfname)) { if (PEAR::isError($MDfname)) {
return $MDfname; return $MDfname;
} }
@ -1032,7 +1083,7 @@ class BasicStor {
$string = $r = $storedFile->outputToM3u(); $string = $r = $storedFile->outputToM3u();
break; break;
default: default:
$string = $r = $storedFile->md->genXmlDoc(); // $string = $r = $storedFile->md->genXmlDoc();
} }
if (PEAR::isError($r)) { if (PEAR::isError($r)) {
return $r; return $r;

View File

@ -401,37 +401,43 @@ class DataEngine {
// Each metadata value is LEFT JOINED to the results, and has the // Each metadata value is LEFT JOINED to the results, and has the
// name of its qualified name with ":" replaced with "_". // name of its qualified name with ":" replaced with "_".
// Here we also make the ORDER BY clause. // Here we also make the ORDER BY clause.
$metadataJoinSql = array(); // $metadataJoinSql = array();
$orderBySql = array(); $orderBySql = array();
// $dataName contains the names of the metadata columns we want to // $dataName contains the names of the metadata columns we want to
// fetch. It is indexed numerically starting from 1, and the value // fetch. It is indexed numerically starting from 1, and the value
// in the array is the qualified name with ":" replaced with "_". // in the array is the qualified name with ":" replaced with "_".
// e.g. "dc:creator" becomes "dc_creator". // e.g. "dc:creator" becomes "dc_creator".
$dataName = array(); // $dataName = array();
foreach ($metadataNames as $j => $qname) { // foreach ($metadataNames as $j => $qname) {
$i = $j + 1; // $i = $j + 1;
$obSplitQn = XML_Util::splitQualifiedName($qname); // $obSplitQn = XML_Util::splitQualifiedName($qname);
$obNs = $obSplitQn['namespace']; // $obNs = $obSplitQn['namespace'];
$obLp = $obSplitQn['localPart']; // $obLp = $obSplitQn['localPart'];
$desc = (isset($descA[$j]) ? $descA[$j] : NULL); // $desc = (isset($descA[$j]) ? $descA[$j] : NULL);
$retype = ($obLp == 'mtime' ? '::timestamp with time zone' : '' ); // $retype = ($obLp == 'mtime' ? '::timestamp with time zone' : '' );
$metadataJoinSql[] = // $metadataJoinSql[] =
"LEFT JOIN ".$CC_CONFIG['mdataTable']." m$i\n". // "LEFT JOIN ".$CC_CONFIG['mdataTable']." m$i\n".
" ON m$i.gunid = sq2.gunid AND m$i.predicate='$obLp'". // " ON m$i.gunid = sq2.gunid AND m$i.predicate='$obLp'".
" AND m$i.objns='_L' AND m$i.predxml='T'". // " AND m$i.objns='_L' AND m$i.predxml='T'".
(!is_null($obNs)? " AND m$i.predns='$obNs'":''); // (!is_null($obNs)? " AND m$i.predns='$obNs'":'');
//
// $dataName[$qname] = str_replace(":", "_", $qname);
// if (in_array($qname, $orderbyQns)) {
// $orderBySql[] = $dataName[$qname].$retype.($desc? ' DESC':'');
// }
// }
$dataName[$qname] = str_replace(":", "_", $qname); foreach ($orderbyQns as $xmlTag) {
if (in_array($qname, $orderbyQns)) { $columnName = BasicStor::xmlCategoryToDbColumn($xmlTag);
$orderBySql[] = $dataName[$qname].$retype.($desc? ' DESC':''); $orderBySql[] = $columnName;
}
} }
if (!$orderby) { // if (!$orderby) {
$fldsPart = "DISTINCT to_hex(f.gunid)as gunid, f.ftype, f.id "; // $fldsPart = "DISTINCT to_hex(f.gunid)as gunid, f.ftype, f.id ";
} else { // } else {
$fldsPart = "DISTINCT f.gunid, f.ftype, f.id "; // $fldsPart = "DISTINCT f.gunid, f.ftype, f.id ";
} // }
$fldsPart = " * ";
$fileCond = "(f.state='ready' OR f.state='edited')"; $fileCond = "(f.state='ready' OR f.state='edited')";
if (!is_null($filetype)) { if (!is_null($filetype)) {
@ -442,31 +448,33 @@ class DataEngine {
} else { } else {
$sql = $this->_makeOrSql($fldsPart, $whereArr, $fileCond, false); $sql = $this->_makeOrSql($fldsPart, $whereArr, $fileCond, false);
} }
// the actual values to fetch // the actual values to fetch
if ($orderby) { if ($orderby) {
$tmpSql = "SELECT to_hex(sq2.gunid)as gunid, sq2.ftype, sq2.id"; //$tmpSql = "SELECT to_hex(sq2.gunid)as gunid, sq2.ftype, sq2.id";
$i = 1; $tmpSql = "SELECT * ";
foreach ($metadataNames as $qname) { // $i = 1;
// Special case for track number because if we use text // foreach ($metadataNames as $qname) {
// sorting of this value, then 10 comes right after 1. // // Special case for track number because if we use text
// So we convert track number to an integer for ordering. // // sorting of this value, then 10 comes right after 1.
// // So we convert track number to an integer for ordering.
//
// // PaulB: see my note above about why this is commented out.
// //if ($qname == "ls:track_num") {
// // $tmpSql .= ", CAST(m$i.object as integer) as ls_track_num";
// //} else {
//// $tmpSql .= ", m$i.object as ".$dataName[$qname];
// $tmpSql .= ", m$i.object as ".$dataName[$qname];
// //}
// $i++;
// }
// PaulB: see my note above about why this is commented out. $tmpSql .= "\nFROM \n".$CC_CONFIG["filesTable"]."\n".
//if ($qname == "ls:track_num") {
// $tmpSql .= ", CAST(m$i.object as integer) as ls_track_num";
//} else {
$tmpSql .= ", m$i.object as ".$dataName[$qname];
//}
$i++;
}
$tmpSql .= "\nFROM (\n$sql\n)sq2\n".
join("\n", $metadataJoinSql).
"ORDER BY ".join(",", $orderBySql)."\n"; "ORDER BY ".join(",", $orderBySql)."\n";
$sql = $tmpSql; $sql = $tmpSql;
} }
$_SESSION["debug"] = $tmpSql;
// Get the number of results // Get the number of results
$cnt = $this->_getNumRows($sql); $cnt = $this->_getNumRows($sql);
if (PEAR::isError($cnt)) { if (PEAR::isError($cnt)) {
@ -490,13 +498,24 @@ class DataEngine {
'id' => $it['id'], 'id' => $it['id'],
'gunid' => $gunid, 'gunid' => $gunid,
'type' => strtolower($it['ftype']), 'type' => strtolower($it['ftype']),
'title' => $it['dc_title'], 'title' => $it['track_title'],
'creator' => $it['dc_creator'], 'creator' => $it['artist_name'],
'duration' => $it['dcterms_extent'], 'duration' => $it['length'],
'length' => $it['dcterms_extent'], 'length' => $it['length'],
'source' => $it['dc_source'], 'source' => $it['album_title'],
'track_num' => $it['ls_track_num'], 'track_num' => $it['track_number'],
); );
// $eres[] = array(
// 'id' => $it['id'],
// 'gunid' => $gunid,
// 'type' => strtolower($it['ftype']),
// 'title' => $it['dc_title'],
// 'creator' => $it['dc_creator'],
// 'duration' => $it['dcterms_extent'],
// 'length' => $it['dcterms_extent'],
// 'source' => $it['dc_source'],
// 'track_num' => $it['ls_track_num'],
// );
} }
return array('results'=>$eres, 'cnt'=>$cnt); return array('results'=>$eres, 'cnt'=>$cnt);
} }

View File

@ -1,10 +1,10 @@
<?php <?php
require_once("BasicStor.php"); require_once("BasicStor.php");
if ($WHITE_SCREEN_OF_DEATH) { if (isset($WHITE_SCREEN_OF_DEATH) && $WHITE_SCREEN_OF_DEATH) {
echo __FILE__.':line '.__LINE__.": Loaded BasicStor<br>"; echo __FILE__.':line '.__LINE__.": Loaded BasicStor<br>";
} }
require_once("LocStor.php"); require_once("LocStor.php");
if ($WHITE_SCREEN_OF_DEATH) { if (isset($WHITE_SCREEN_OF_DEATH) && $WHITE_SCREEN_OF_DEATH) {
echo __FILE__.':line '.__LINE__.": Loaded LocStor<br>"; echo __FILE__.':line '.__LINE__.": Loaded LocStor<br>";
} }
require_once('Prefs.php'); require_once('Prefs.php');
@ -282,7 +282,9 @@ class GreenBox extends BasicStor {
if (is_null($storedFile) || PEAR::isError($storedFile)) { if (is_null($storedFile) || PEAR::isError($storedFile)) {
return $storedFile; return $storedFile;
} }
$arr = $storedFile->md->genPhpArray(); return $storedFile->md;
// $arr = $storedFile->md->genPhpArray();
$md = FALSE; $md = FALSE;
foreach ($arr['children'] as $i=>$a) { foreach ($arr['children'] as $i=>$a) {
if ($a['elementname'] == 'metadata'){ if ($a['elementname'] == 'metadata'){
@ -365,7 +367,7 @@ class GreenBox extends BasicStor {
if (($res = BasicStor::Authorize('write', $id, $sessid)) !== TRUE) { if (($res = BasicStor::Authorize('write', $id, $sessid)) !== TRUE) {
return $res; return $res;
} }
return $this->bsSetMetadataValue($id, $category, $value, $lang, $mid); return $this->bsSetMetadataValue($id, $category, $value /*, $lang, $mid*/);
} // fn setMetadataValue } // fn setMetadataValue
@ -565,10 +567,10 @@ class GreenBox extends BasicStor {
if (is_null($storedFile) || PEAR::isError($storedFile)) { if (is_null($storedFile) || PEAR::isError($storedFile)) {
return $storedFile; return $storedFile;
} }
$r = $storedFile->md->regenerateXmlFile(); // $r = $storedFile->md->regenerateXmlFile();
if (PEAR::isError($r)) { // if (PEAR::isError($r)) {
return $r; // return $r;
} // }
$this->setEditFlag($gunid, FALSE, $sessid); $this->setEditFlag($gunid, FALSE, $sessid);
return $gunid; return $gunid;
} // fn releaseLockedPlaylist } // fn releaseLockedPlaylist

View File

@ -1,10 +1,10 @@
<?php <?php
require_once("BasicStor.php"); require_once("BasicStor.php");
if ($WHITE_SCREEN_OF_DEATH) { if (isset($WHITE_SCREEN_OF_DEATH) && $WHITE_SCREEN_OF_DEATH) {
echo __FILE__.':line '.__LINE__.": Loaded BasicStor<br>"; echo __FILE__.':line '.__LINE__.": Loaded BasicStor<br>";
} }
require_once("Transport.php"); require_once("Transport.php");
if ($WHITE_SCREEN_OF_DEATH) { if (isset($WHITE_SCREEN_OF_DEATH) && $WHITE_SCREEN_OF_DEATH) {
echo __FILE__.':line '.__LINE__.": Loaded Transport<br>"; echo __FILE__.':line '.__LINE__.": Loaded Transport<br>";
} }
@ -196,7 +196,7 @@ class LocStor extends BasicStor {
} }
$oid = $storedFile->getId(); $oid = $storedFile->getId();
$r = $this-> bsSetMetadataValue( $r = $this-> bsSetMetadataValue(
$oid, 'ls:url', $url, NULL, NULL, 'metadata'); $oid, 'ls:url', $url /*, NULL, NULL, 'metadata'*/);
if (PEAR::isError($r)) { if (PEAR::isError($r)) {
return $r; return $r;
} }

View File

@ -49,7 +49,7 @@ class MetaData {
/** /**
* @var array * @var array
*/ */
private $metadata; private $metadata;
/** /**
@ -278,30 +278,13 @@ class MetaData {
public function setMetadataElement($p_id, $p_value=NULL) public function setMetadataElement($p_id, $p_value=NULL)
{ {
global $CC_CONFIG, $CC_DBC; global $CC_CONFIG, $CC_DBC;
$info = $CC_DBC->getRow(" // $r = $this->validateOneValue($parname, $category, $predxml, $p_value);
SELECT parmd.predns as parns, parmd.predicate as parname, // if (PEAR::isError($r)) {
md.predxml, md.predns as chns, md.predicate as chname // return $r;
FROM ".$CC_CONFIG['mdataTable']." parmd // }
INNER JOIN ".$CC_CONFIG['mdataTable']." md
ON parmd.id=md.subject::integer AND md.subjns='_I'
WHERE md.id=$p_id");
if (PEAR::isError($info)) {
return $info;
}
if (is_null($info)) {
return PEAR::raiseError(
"MetaData::setMetadataElement: parent container not found");
}
extract($info);
$parname = ($parns ? "$parns:" : '').$parname;
$category = ($chns ? "$chns:" : '').$chname;
$r = $this->validateOneValue($parname, $category, $predxml, $p_value);
if (PEAR::isError($r)) {
return $r;
}
if (!is_null($p_value)) { if (!is_null($p_value)) {
$escapedValue = pg_escape_string($p_value); $escapedValue = pg_escape_string($p_value);
$sql = "UPDATE ".$CC_CONFIG['mdataTable']." $sql = "UPDATE ".$CC_CONFIG['filesTable']."
SET object='$escapedValue', objns='_L' SET object='$escapedValue', objns='_L'
WHERE id={$p_id}"; WHERE id={$p_id}";
$res = $CC_DBC->query($sql); $res = $CC_DBC->query($sql);
@ -523,6 +506,7 @@ class MetaData {
} }
$parid = $contArr[0]['mid']; $parid = $contArr[0]['mid'];
if (is_null($parid)) { if (is_null($parid)) {
//var_dump($contArr);
return PEAR::raiseError( return PEAR::raiseError(
"MetaData::setMetadataValue: container ($p_container) not found" "MetaData::setMetadataValue: container ($p_container) not found"
); );
@ -746,7 +730,6 @@ class MetaData {
*/ */
private function storeNode(&$node, $parid=NULL, $nSpaces=array()) private function storeNode(&$node, $parid=NULL, $nSpaces=array())
{ {
//echo $node->node_name().", ".$node->node_type().", ".$node->prefix().", $parid.\n";
$nSpaces = array_merge($nSpaces, $node->nSpaces); $nSpaces = array_merge($nSpaces, $node->nSpaces);
// null parid = root node of metadata tree // null parid = root node of metadata tree
$subjns = (is_null($parid)? '_G' : '_I'); $subjns = (is_null($parid)? '_G' : '_I');
@ -758,12 +741,10 @@ class MetaData {
} else { } else {
$objns = '_L'; $objns = '_L';
} }
$id = $this->storeRecord($subjns, $subject, $id = $this->storeRecord($subjns, $subject, $node->ns, $node->name, 'T', $objns, $object);
$node->ns, $node->name, 'T', $objns, $object);
// process attributes // process attributes
foreach ($node->attrs as $atn => $ato) { foreach ($node->attrs as $atn => $ato) {
$this->storeRecord('_I', $id, $this->storeRecord('_I', $id, $ato->ns, $ato->name, 'A', '_L', $ato->val);
$ato->ns, $ato->name, 'A', '_L', $ato->val);
} }
// process child nodes // process child nodes
foreach ($node->children as $ch) { foreach ($node->children as $ch) {
@ -771,8 +752,7 @@ class MetaData {
} }
// process namespace definitions // process namespace definitions
foreach ($node->nSpaces as $ns => $uri) { foreach ($node->nSpaces as $ns => $uri) {
$this->storeRecord('_I', $id, $this->storeRecord('_I', $id, 'xmlns', $ns, 'N', '_L', $uri);
'xmlns', $ns, 'N', '_L', $uri);
} }
return $id; return $id;
} }
@ -841,7 +821,7 @@ class MetaData {
$predicate_sql = is_null($predicate) ? "NULL" : "'".pg_escape_string($predicate)."'"; $predicate_sql = is_null($predicate) ? "NULL" : "'".pg_escape_string($predicate)."'";
$objns_sql = is_null($objns) ? "NULL" : "'".pg_escape_string($objns)."'"; $objns_sql = is_null($objns) ? "NULL" : "'".pg_escape_string($objns)."'";
$object_sql = is_null($object) ? "NULL" : "'".pg_escape_string($object)."'"; $object_sql = is_null($object) ? "NULL" : "'".pg_escape_string($object)."'";
$id = $CC_DBC->nextId($CC_CONFIG['mdataTable']."_id_seq"); $id = $CC_DBC->nextId($CC_CONFIG['mdataSequence']);
if (PEAR::isError($id)) { if (PEAR::isError($id)) {
return $id; return $id;
} }
@ -851,7 +831,7 @@ class MetaData {
predns, predicate, predxml, predns, predicate, predxml,
objns, object) objns, object)
VALUES VALUES
($id, x'{$this->gunid}'::bigint, $subjns_sql, $subject_sql, (DEFAULT, x'{$this->gunid}'::bigint, $subjns_sql, $subject_sql,
$predns_sql, $predicate_sql, '$predxml', $predns_sql, $predicate_sql, '$predxml',
$objns_sql, $object_sql $objns_sql, $object_sql
)"); )");

View File

@ -285,7 +285,7 @@ class Prefs {
public static function Insert($subjid, $keystr, $valstr='') public static function Insert($subjid, $keystr, $valstr='')
{ {
global $CC_CONFIG, $CC_DBC; global $CC_CONFIG, $CC_DBC;
$id = $CC_DBC->nextId($CC_CONFIG['prefTable']."_id_seq"); $id = $CC_DBC->nextId($CC_CONFIG['prefSequence']);
if (PEAR::isError($id)) { if (PEAR::isError($id)) {
return $id; return $id;
} }

View File

@ -1,5 +1,5 @@
<?php <?php
require_once("MetaData.php"); //require_once("MetaData.php");
require_once("Playlist.php"); require_once("Playlist.php");
require_once(dirname(__FILE__)."/../../getid3/var/getid3.php"); require_once(dirname(__FILE__)."/../../getid3/var/getid3.php");
@ -390,9 +390,71 @@ class StoredFile {
$this->resDir = $this->_getResDir($this->gunid); $this->resDir = $this->_getResDir($this->gunid);
$this->filepath = "{$this->resDir}/{$this->gunid}"; $this->filepath = "{$this->resDir}/{$this->gunid}";
$this->exists = is_file($this->filepath) && is_readable($this->filepath); $this->exists = is_file($this->filepath) && is_readable($this->filepath);
$this->md = new MetaData($this->gunid, $this->resDir); $this->md = $this->loadMetadata();
} }
public function loadMetadata()
{
global $CC_CONFIG, $CC_DBC;
$escapedValue = pg_escape_string($this->gunid);
$sql = "SELECT * FROM ".$CC_CONFIG["filesTable"]
." WHERE gunid=x'$escapedValue'::bigint";
//var_dump($sql);
$this->md = $CC_DBC->getRow($sql);
if (PEAR::isError($this->md)) {
$error = $this->md;
$this->md = null;
return $error;
}
if (is_null($this->md)) {
$this->md = array();
return;
}
$compatibilityData = array();
foreach ($this->md as $key => $value) {
if ($xmlName = BasicStor::dbColumnToXmlCatagory($key)) {
$compatibilityData[$xmlName] = $value;
}
}
$this->md = array_merge($this->md, $compatibilityData);
//$_SESSION["debug"] = $this->md;
}
public function setFormat($p_value)
{
$this->md["format"] = $p_value;
}
public function replaceMetadata($p_values)
{
global $CC_CONFIG, $CC_DBC;
foreach ($p_values as $category => $value) {
$escapedValue = pg_escape_string($value);
$columnName = BasicStor::xmlCategoryToDbColumn($category);
if (!is_null($columnName)) {
$sql = "UPDATE ".$CC_CONFIG["filesTable"]
." SET $columnName='$escapedValue'"
." WHERE gunid = '".$this->gunid."'";
$CC_DBC->query($sql);
}
}
$this->loadMetadata();
}
public function clearMetadata()
{
$metadataColumns = array("format", "bit_rate", "sample_rate", "length",
"track_title", "comments", "genre", "artist_name", "channels", "name",
"year", "url", "track_number");
foreach ($metadataColumns as $columnName) {
if (!is_null($columnName)) {
$sql = "UPDATE ".$CC_CONFIG["filesTable"]
." SET $columnName=''"
." WHERE gunid = '".$this->gunid."'";
$CC_DBC->query($sql);
}
}
}
/* ========= 'factory' methods - should be called to construct StoredFile */ /* ========= 'factory' methods - should be called to construct StoredFile */
/** /**
@ -458,29 +520,31 @@ class StoredFile {
if (!is_integer($storedFile->id)) { if (!is_integer($storedFile->id)) {
// NOTE: POSTGRES-SPECIFIC // NOTE: POSTGRES-SPECIFIC
$sql = "SELECT currval('".$CC_CONFIG["filesSequence"]."')"; $sql = "SELECT currval('".$CC_CONFIG["filesSequence"]."_seq')";
$storedFile->id = $CC_DBC->getOne($sql); $storedFile->id = $CC_DBC->getOne($sql);
} }
// Insert metadata // Insert metadata
$metadata = $p_values['metadata']; $metadata = $p_values['metadata'];
BasicStor::bsSetMetadataBatch($storedFile->id, $metadata);
// $mdataLoc = ($metadata[0]=="/")? "file":"string"; // $mdataLoc = ($metadata[0]=="/")? "file":"string";
// for non-absolute paths: // for non-absolute paths:
$mdataLoc = ($metadata[0]!="<")? "file":"string"; // $mdataLoc = ($metadata[0]!="<")? "file":"string";
if (is_null($metadata) || ($metadata == '') ) { // if (is_null($metadata) || ($metadata == '') ) {
$metadata = dirname(__FILE__).'/emptyMdata.xml'; // $metadata = dirname(__FILE__).'/emptyMdata.xml';
$mdataLoc = 'file'; // $mdataLoc = 'file';
} else { // } else {
$emptyState = FALSE; // $emptyState = FALSE;
} // }
if ( ($mdataLoc == 'file') && !file_exists($metadata)) { // if ( ($mdataLoc == 'file') && !file_exists($metadata)) {
return PEAR::raiseError("StoredFile::Insert: ". // return PEAR::raiseError("StoredFile::Insert: ".
"metadata file not found ($metadata)"); // "metadata file not found ($metadata)");
} // }
$res = $storedFile->md->insert($metadata, $mdataLoc, $storedFile->ftype); // $res = $storedFile->md->insert($metadata, $mdataLoc, $storedFile->ftype);
if (PEAR::isError($res)) { // if (PEAR::isError($res)) {
$CC_DBC->query("ROLLBACK"); // $CC_DBC->query("ROLLBACK");
return $res; // return $res;
} // }
// Save media file // Save media file
if (!empty($p_values['filepath'])) { if (!empty($p_values['filepath'])) {
@ -567,7 +631,8 @@ class StoredFile {
$storedFile = new StoredFile($gunid); $storedFile = new StoredFile($gunid);
} }
$storedFile->gunidBigint = $row['gunid_bigint']; $storedFile->gunidBigint = $row['gunid_bigint'];
$storedFile->md->gunidBigint = $row['gunid_bigint']; //$storedFile->md->gunidBigint = $row['gunid_bigint'];
$storedFile->md["gunid"] = $row['gunid_bigint'];
$storedFile->id = $row['id']; $storedFile->id = $row['id'];
$storedFile->name = $row['name']; $storedFile->name = $row['name'];
$storedFile->mime = $row['mime']; $storedFile->mime = $row['mime'];
@ -578,7 +643,7 @@ class StoredFile {
$storedFile->mtime = $row['mtime']; $storedFile->mtime = $row['mtime'];
$storedFile->md5 = $row['md5']; $storedFile->md5 = $row['md5'];
$storedFile->exists = TRUE; $storedFile->exists = TRUE;
$storedFile->md->setFormat($row['ftype']); $storedFile->setFormat($row['ftype']);
return $storedFile; return $storedFile;
} }
@ -772,7 +837,7 @@ class StoredFile {
if (PEAR::isError($storedFile)) { if (PEAR::isError($storedFile)) {
return $storedFile; return $storedFile;
} }
$storedFile->md->replace($p_src->md->getMetadata(), 'string'); $storedFile->replaceMetadata($p_src->getAllMetadata(), 'string');
return $storedFile; return $storedFile;
} }
@ -814,7 +879,8 @@ class StoredFile {
if ($p_metadata != '') { if ($p_metadata != '') {
$res = $this->setMetadata($p_metadata, $p_mdataLoc); $res = $this->setMetadata($p_metadata, $p_mdataLoc);
} else { } else {
$res = $this->md->delete(); // $res = $this->md->delete();
$res = $this->clearMetadata();
} }
if (PEAR::isError($res)) { if (PEAR::isError($res)) {
$CC_DBC->query("ROLLBACK"); $CC_DBC->query("ROLLBACK");
@ -888,10 +954,10 @@ class StoredFile {
return $res; return $res;
} }
} }
$r = $this->md->regenerateXmlFile(); // $r = $this->md->regenerateXmlFile();
if (PEAR::isError($r)) { // if (PEAR::isError($r)) {
return $r; // return $r;
} // }
return TRUE; return TRUE;
} }
@ -918,11 +984,11 @@ class StoredFile {
$CC_DBC->query("ROLLBACK"); $CC_DBC->query("ROLLBACK");
return $res; return $res;
} }
$r = $this->md->regenerateXmlFile(); // $r = $this->md->regenerateXmlFile();
if (PEAR::isError($r)) { // if (PEAR::isError($r)) {
$CC_DBC->query("ROLLBACK"); // $CC_DBC->query("ROLLBACK");
return $r; // return $r;
} // }
$res = $CC_DBC->query("COMMIT"); $res = $CC_DBC->query("COMMIT");
if (PEAR::isError($res)) { if (PEAR::isError($res)) {
return $res; return $res;
@ -939,7 +1005,8 @@ class StoredFile {
*/ */
public function getMetadata() public function getMetadata()
{ {
return $this->md->getMetadata(); //return $this->md->getMetadata();
return $this->md;
} }
@ -1056,10 +1123,10 @@ class StoredFile {
return $res; return $res;
} }
} }
$res = $this->md->delete(); // $res = $this->md->delete();
if (PEAR::isError($res)) { // if (PEAR::isError($res)) {
return $res; // return $res;
} // }
$sql = "SELECT to_hex(token)as token, ext " $sql = "SELECT to_hex(token)as token, ext "
." FROM ".$CC_CONFIG['accessTable'] ." FROM ".$CC_CONFIG['accessTable']
." WHERE gunid=x'{$this->gunid}'::bigint"; ." WHERE gunid=x'{$this->gunid}'::bigint";
@ -1370,7 +1437,8 @@ class StoredFile {
*/ */
public function getRealMetadataFileName() public function getRealMetadataFileName()
{ {
return $this->md->getFileName(); //return $this->md->getFileName();
return $this->md["name"];
} }

View File

@ -34,7 +34,6 @@ include_once("TransportRecord.php");
* <ul> * <ul>
* <li>audioclip</li> * <li>audioclip</li>
* <li>playlist</li> * <li>playlist</li>
* <li>searchjob</li>
* <li>metadata</li> * <li>metadata</li>
* <li>file</li> * <li>file</li>
* </ul> * </ul>
@ -139,7 +138,7 @@ class Transport
* @return array * @return array
* struct/hasharray with fields: * struct/hasharray with fields:
* trtype: string - * trtype: string -
* audioclip | playlist | playlistPkg | search | metadata | file * audioclip | playlist | playlistPkg | metadata | file
* state: string - transport state * state: string - transport state
* init | pending | waiting | finished | closed | failed * init | pending | waiting | finished | closed | failed
* direction: string - up | down * direction: string - up | down
@ -175,11 +174,6 @@ class Transport
$res['realsum'] = $check['realsum']; $res['realsum'] = $check['realsum'];
} }
} }
// do not return finished on finished search job upload
// - whole search is NOT finished
if ($res['trtype'] == "searchjob" && $res['direction'] == "up" && $res['state'] == "finished") {
$res['state'] = "waiting";
}
return $res; return $res;
} }
@ -1045,9 +1039,9 @@ class Transport
$title = $ret['title']; $title = $ret['title'];
$pars = array(); $pars = array();
switch ($trtype) { switch ($trtype) {
case "searchjob": // case "searchjob":
$r = $trec->setState('waiting', $pars); // $r = $trec->setState('waiting', $pars);
break; // break;
case "file": case "file":
$r = $trec->setState('waiting',array_merge($pars, array( $r = $trec->setState('waiting',array_merge($pars, array(
'trtype'=>$trtype, 'trtype'=>$trtype,
@ -1331,20 +1325,20 @@ class Transport
return $ret; return $ret;
} }
if ($row['trtype'] == 'searchjob') { // if ($row['trtype'] == 'searchjob') {
@unlink($row['localfile']); // @unlink($row['localfile']);
$r = $trec->setState('init', array( // $r = $trec->setState('init', array(
'direction' => 'down', // 'direction' => 'down',
'pdtoken' => $ret['token'], // 'pdtoken' => $ret['token'],
'expectedsum' => $ret['chsum'], // 'expectedsum' => $ret['chsum'],
'expectedsize' => $ret['size'], // 'expectedsize' => $ret['size'],
'url' => $ret['url'], // 'url' => $ret['url'],
'realsize' => 0, // 'realsize' => 0,
)); // ));
$this->startCronJobProcess($trec->trtok); // $this->startCronJobProcess($trec->trtok);
} else { // } else {
$r = $trec->close(); $r = $trec->close();
} // }
if (PEAR::isError($r)) { if (PEAR::isError($r)) {
return $r; return $r;
} }
@ -1497,7 +1491,7 @@ class Transport
break; break;
case "audioclip": case "audioclip":
case "metadata": case "metadata":
case "searchjob": // case "searchjob":
case "file": case "file":
break; break;
default: default:
@ -1675,7 +1669,6 @@ class Transport
$key = 'archiveServerLocation'; $key = 'archiveServerLocation';
$archiveUrl = $pr->loadGroupPref($group, $key, false); $archiveUrl = $pr->loadGroupPref($group, $key, false);
echo "Archive URL: $archiveUrl\n";
if ($archiveUrl) { if ($archiveUrl) {
$archiveUrlInfo = parse_url($archiveUrl); $archiveUrlInfo = parse_url($archiveUrl);
if ($archiveUrlInfo['port']) { if ($archiveUrlInfo['port']) {
@ -1835,87 +1828,6 @@ class Transport
return $CC_DBC->query("DELETE FROM ".$CC_CONFIG['transTable']); return $CC_DBC->query("DELETE FROM ".$CC_CONFIG['transTable']);
} }
/**
* Install method<br>
*
* direction: up | down
* state: init | pending | waiting | finished | closed | failed | paused
* trtype: audioclip | playlist | playlistPkg | searchjob | metadata | file
*
*/
// function install()
// {
// global $CC_CONFIG, $CC_DBC;
// $r = $CC_DBC->query("CREATE TABLE {$this->transTable} (
// id int not null, -- primary key
// trtok char(16) not null, -- transport token
// direction varchar(128) not null, -- direction: up|down
// state varchar(128) not null, -- state
// trtype varchar(128) not null, -- transport type
// lock char(1) not null default 'N',-- running lock
// target varchar(255) default NULL, -- target system,
// -- if NULL => predefined set
// rtrtok char(16) default NULL, -- remote hub's transport token
// mdtrtok char(16), -- metadata transport token
// gunid bigint, -- global unique id
// pdtoken bigint, -- put/download token from archive
// url varchar(255), -- url on remote side
// localfile varchar(255), -- pathname of local part
// fname varchar(255), -- mnemonic filename
// title varchar(255), -- dc:title mdata value (or filename ...)
// expectedsum char(32), -- expected file checksum
// realsum char(32), -- checksum of transported part
// expectedsize int, -- expected filesize in bytes
// realsize int, -- filesize of transported part
// uid int, -- local user id of transport owner
// errmsg varchar(255), -- error message string for failed tr.
// start timestamp, -- starttime
// ts timestamp -- mtime
// )");
// if (PEAR::isError($r)) {
// echo $r->getMessage()." ".$r->getUserInfo();
// }
// $r = $CC_DBC->createSequence("{$this->transTable}_id_seq");
// if (PEAR::isError($r)) {
// echo $r->getMessage()." ".$r->getUserInfo();
// }
// $r = $CC_DBC->query("CREATE UNIQUE INDEX {$this->transTable}_id_idx
// ON {$this->transTable} (id)");
// if (PEAR::isError($r)) {
// echo $r->getMessage()." ".$r->getUserInfo();
// }
// $r = $CC_DBC->query("CREATE UNIQUE INDEX {$this->transTable}_trtok_idx
// ON {$this->transTable} (trtok)");
// if (PEAR::isError($r)) {
// echo $r->getMessage()." ".$r->getUserInfo();
// }
// $r = $CC_DBC->query("CREATE UNIQUE INDEX {$this->transTable}_token_idx
// ON {$this->transTable} (pdtoken)");
// if (PEAR::isError($r)) {
// echo $r->getMessage()." ".$r->getUserInfo();
// }
// $r = $CC_DBC->query("CREATE INDEX {$this->transTable}_gunid_idx
// ON {$this->transTable} (gunid)");
// if (PEAR::isError($r)) {
// echo $r->getMessage()." ".$r->getUserInfo();
// }
// $r = $CC_DBC->query("CREATE INDEX {$this->transTable}_state_idx
// ON {$this->transTable} (state)");
// if (PEAR::isError($r)) {
// echo $r->getMessage()." ".$r->getUserInfo();
// }
// }
/**
* Uninstall method
*/
// function uninstall()
// {
// global $CC_CONFIG, $CC_DBC;
// $CC_DBC->query("DROP TABLE {$this->transTable}");
// $CC_DBC->dropSequence("{$this->transTable}_id_seq");
// }
} }
?> ?>

View File

@ -80,7 +80,7 @@ class TransportRecord
return $defaults['title']; return $defaults['title'];
} }
} }
$id = $CC_DBC->nextId($CC_CONFIG['transTable']."_id_seq"); $id = $CC_DBC->nextId($CC_CONFIG['transSequence']);
$names = "id, trtok, direction, state, trtype, start, ts"; $names = "id, trtok, direction, state, trtype, start, ts";
$values = "$id, '$trtok', '$direction', 'init', '$trtype', now(), now()"; $values = "$id, '$trtok', '$direction', 'init', '$trtype', now(), now()";
foreach ($defaults as $k => $v) { foreach ($defaults as $k => $v) {

View File

@ -126,7 +126,14 @@ $CC_CONFIG['prefTable'] = $CC_CONFIG['tblNamePrefix'].'pref';
$CC_CONFIG['playlogTable'] = $CC_CONFIG['tblNamePrefix'].'playlog'; $CC_CONFIG['playlogTable'] = $CC_CONFIG['tblNamePrefix'].'playlog';
$CC_CONFIG['scheduleTable'] = $CC_CONFIG['tblNamePrefix'].'schedule'; $CC_CONFIG['scheduleTable'] = $CC_CONFIG['tblNamePrefix'].'schedule';
$CC_CONFIG['backupTable'] = $CC_CONFIG['tblNamePrefix'].'backup'; $CC_CONFIG['backupTable'] = $CC_CONFIG['tblNamePrefix'].'backup';
$CC_CONFIG['filesSequence'] = $CC_CONFIG['tblNamePrefix']."file_id_seq";
$CC_CONFIG['filesSequence'] = $CC_CONFIG['filesTable'].'_id';
$CC_CONFIG['transSequence'] = $CC_CONFIG['transTable'].'_id';
$CC_CONFIG['prefSequence'] = $CC_CONFIG['prefTable'].'_id';
$CC_CONFIG['permSequence'] = $CC_CONFIG['permTable'].'_id';
$CC_CONFIG['subjSequence'] = $CC_CONFIG['subjTable'].'_id';
$CC_CONFIG['smembSequence'] = $CC_CONFIG['smembTable'].'_id';
$CC_CONFIG['mdataSequence'] = $CC_CONFIG['mdataTable'].'_id';
$CC_CONFIG['sysSubjs'] = array( $CC_CONFIG['sysSubjs'] = array(
'root', /*$CC_CONFIG['AdminsGr'],*/ /*$CC_CONFIG['AllGr'],*/ $CC_CONFIG['StationPrefsGr'] 'root', /*$CC_CONFIG['AdminsGr'],*/ /*$CC_CONFIG['AllGr'],*/ $CC_CONFIG['StationPrefsGr']

View File

@ -7,8 +7,6 @@
* *
*/ */
$WHITE_SCREEN_OF_DEATH = false;
// Do not allow remote execution // Do not allow remote execution
$arr = array_diff_assoc($_SERVER, $_ENV); $arr = array_diff_assoc($_SERVER, $_ENV);
if (isset($arr["DOCUMENT_ROOT"]) && ($arr["DOCUMENT_ROOT"] != "") ) { if (isset($arr["DOCUMENT_ROOT"]) && ($arr["DOCUMENT_ROOT"] != "") ) {
@ -22,9 +20,9 @@ echo "*************************\n";
echo "* StorageServer Install *\n"; echo "* StorageServer Install *\n";
echo "*************************\n"; echo "*************************\n";
require_once('../conf.php'); require_once(dirname(__FILE__).'/../conf.php');
require_once('../GreenBox.php'); require_once(dirname(__FILE__).'/../GreenBox.php');
require_once("installInit.php"); require_once(dirname(__FILE__)."/installInit.php");
campcaster_db_connect(true); campcaster_db_connect(true);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@ -51,7 +49,7 @@ if (!camp_db_table_exists($CC_CONFIG['subjTable'])) {
ON ".$CC_CONFIG['subjTable']." (login)"; ON ".$CC_CONFIG['subjTable']." (login)";
camp_install_query($sql, false); camp_install_query($sql, false);
$CC_DBC->createSequence($CC_CONFIG['subjTable']."_id_seq"); $CC_DBC->createSequence($CC_CONFIG['subjSequence']);
echo "done.\n"; echo "done.\n";
} else { } else {
echo " * Skipping: database table already exists: ".$CC_CONFIG['subjTable']."\n"; echo " * Skipping: database table already exists: ".$CC_CONFIG['subjTable']."\n";
@ -71,7 +69,7 @@ if (!camp_db_table_exists($CC_CONFIG['smembTable'])) {
ON ".$CC_CONFIG['smembTable']." (id)"; ON ".$CC_CONFIG['smembTable']." (id)";
camp_install_query($sql, false); camp_install_query($sql, false);
$CC_DBC->createSequence($CC_CONFIG['smembTable']."_id_seq"); //$CC_DBC->createSequence($CC_CONFIG['smembSequence']);
echo "done.\n"; echo "done.\n";
} else { } else {
echo " * Skipping: database table already exists: ".$CC_CONFIG['smembTable']."\n"; echo " * Skipping: database table already exists: ".$CC_CONFIG['smembTable']."\n";
@ -99,7 +97,7 @@ if (!camp_db_table_exists($CC_CONFIG['permTable'])) {
ON ".$CC_CONFIG['permTable']." (subj, action, obj)"; ON ".$CC_CONFIG['permTable']." (subj, action, obj)";
camp_install_query($sql, false); camp_install_query($sql, false);
$CC_DBC->createSequence($CC_CONFIG['permTable']."_id_seq"); //$CC_DBC->createSequence($CC_CONFIG['permSequence']);
echo "done.\n"; echo "done.\n";
} else { } else {
echo " * Skipping: database table already exists: ".$CC_CONFIG['permTable']."\n"; echo " * Skipping: database table already exists: ".$CC_CONFIG['permTable']."\n";
@ -114,9 +112,9 @@ if (!camp_db_table_exists($CC_CONFIG['sessTable'])) {
ts timestamp)"; ts timestamp)";
camp_install_query($sql, false); camp_install_query($sql, false);
$sql = "CREATE UNIQUE INDEX ".$CC_CONFIG['sessTable']."_sessid_idx // $sql = "CREATE UNIQUE INDEX ".$CC_CONFIG['sessTable']."_sessid_idx
ON ".$CC_CONFIG['sessTable']." (sessid)"; // ON ".$CC_CONFIG['sessTable']." (sessid)";
camp_install_query($sql, false); // camp_install_query($sql, false);
$sql = "CREATE INDEX ".$CC_CONFIG['sessTable']."_userid_idx $sql = "CREATE INDEX ".$CC_CONFIG['sessTable']."_userid_idx
ON ".$CC_CONFIG['sessTable']." (userid)"; ON ".$CC_CONFIG['sessTable']." (userid)";
@ -152,23 +150,43 @@ if (!camp_db_table_exists($CC_CONFIG['sessTable'])) {
*/ */
if (!camp_db_table_exists($CC_CONFIG['filesTable'])) { if (!camp_db_table_exists($CC_CONFIG['filesTable'])) {
echo " * Creating database table ".$CC_CONFIG['filesTable']."..."; echo " * Creating database table ".$CC_CONFIG['filesTable']."...";
$sql = "CREATE TABLE ".$CC_CONFIG['filesTable']." ( $sql =
id int not null, "CREATE TABLE ".$CC_CONFIG['filesTable']."
gunid bigint not null, -- global unique ID (
name varchar(255) not null default'', -- human file id ;) id serial NOT NULL,
mime varchar(255) not null default'', -- mime type gunid bigint NOT NULL,
ftype varchar(128) not null default'', -- file type \"name\" character varying(255) NOT NULL DEFAULT ''::character varying,
state varchar(128) not null default'empty', -- file state mime character varying(255) NOT NULL DEFAULT ''::character varying,
currentlyaccessing int not null default 0, -- access counter ftype character varying(128) NOT NULL DEFAULT ''::character varying,
editedby int REFERENCES ".$CC_CONFIG['subjTable'].", -- who edits it state character varying(128) NOT NULL DEFAULT 'empty'::character varying,
mtime timestamp(6) with time zone, -- lst modif.time currentlyaccessing integer NOT NULL DEFAULT 0,
md5 char(32) editedby integer,
)"; mtime timestamp(6) with time zone,
md5 character(32),
track_title character varying(512),
artist_name character varying(512),
bit_rate character varying(32),
sample_rate character varying(32),
format character varying(128),
length character(16),
album_title character varying(512),
genre character varying(64),
comments text,
\"year\" character varying(16),
track_number integer,
channels integer,
url character varying(1024),
CONSTRAINT cc_files_pkey PRIMARY KEY (id),
CONSTRAINT cc_files_editedby_fkey FOREIGN KEY (editedby)
REFERENCES cc_subjs (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
)";
camp_install_query($sql, false); camp_install_query($sql, false);
$sql = "CREATE UNIQUE INDEX ".$CC_CONFIG['filesTable']."_id_idx // $sql = "CREATE UNIQUE INDEX ".$CC_CONFIG['filesTable']."_id_idx
ON ".$CC_CONFIG['filesTable']." (id)"; // ON ".$CC_CONFIG['filesTable']." (id)";
camp_install_query($sql, false); // camp_install_query($sql, false);
$sql = "CREATE UNIQUE INDEX ".$CC_CONFIG['filesTable']."_gunid_idx $sql = "CREATE UNIQUE INDEX ".$CC_CONFIG['filesTable']."_gunid_idx
ON ".$CC_CONFIG['filesTable']." (gunid)"; ON ".$CC_CONFIG['filesTable']." (gunid)";
@ -182,22 +200,25 @@ if (!camp_db_table_exists($CC_CONFIG['filesTable'])) {
ON ".$CC_CONFIG['filesTable']." (md5)"; ON ".$CC_CONFIG['filesTable']." (md5)";
camp_install_query($sql); camp_install_query($sql);
//$CC_DBC->createSequence($CC_CONFIG['filesSequence']);
} else { } else {
echo " * Skipping: database table already exists: ".$CC_CONFIG['filesTable']."\n"; echo " * Skipping: database table already exists: ".$CC_CONFIG['filesTable']."\n";
} }
if (!camp_db_sequence_exists($CC_CONFIG["filesSequence"])) { //if (!camp_db_sequence_exists($CC_CONFIG["filesSequence"])) {
echo " * Creating database sequence ".$CC_CONFIG['filesSequence']."..."; // echo " * Creating database sequence for ".$CC_CONFIG['filesTable']."...\n";
$sql = "CREATE SEQUENCE ".$CC_CONFIG["filesSequence"] // $CC_DBC->createSequence($CC_CONFIG['filesSequence']);
." INCREMENT 1 //// $sql = "CREATE SEQUENCE ".$CC_CONFIG["filesSequence"]
MINVALUE 1 //// ." INCREMENT 1
MAXVALUE 9223372036854775807 //// MINVALUE 1
START 1000000 //// MAXVALUE 9223372036854775807
CACHE 1"; //// START 1000000
camp_install_query($sql); //// CACHE 1";
} else { //// camp_install_query($sql);
echo " * Skipping: database sequence already exists: ".$CC_CONFIG['filesSequence']."\n"; //} else {
} // echo " * Skipping: database sequence already exists: ".$CC_CONFIG['filesSequence']."\n";
//}
/** /**
* id subjns subject predns predicate objns object * id subjns subject predns predicate objns object
@ -214,9 +235,9 @@ if (!camp_db_sequence_exists($CC_CONFIG["filesSequence"])) {
*/ */
if (!camp_db_table_exists($CC_CONFIG['mdataTable'])) { if (!camp_db_table_exists($CC_CONFIG['mdataTable'])) {
echo " * Creating database table ".$CC_CONFIG['mdataTable']."..."; echo " * Creating database table ".$CC_CONFIG['mdataTable']."...";
$CC_DBC->createSequence($CC_CONFIG['mdataTable']."_id_seq"); //$CC_DBC->createSequence($CC_CONFIG['mdataSequence']);
$sql = "CREATE TABLE ".$CC_CONFIG['mdataTable']." ( $sql = "CREATE TABLE ".$CC_CONFIG['mdataTable']." (
id int not null, id SERIAL PRIMARY KEY,
gunid bigint, gunid bigint,
subjns varchar(255), -- subject namespace shortcut/uri subjns varchar(255), -- subject namespace shortcut/uri
subject varchar(255) not null default '', subject varchar(255) not null default '',
@ -228,9 +249,9 @@ if (!camp_db_table_exists($CC_CONFIG['mdataTable'])) {
)"; )";
camp_install_query($sql, false); camp_install_query($sql, false);
$sql = "CREATE UNIQUE INDEX ".$CC_CONFIG['mdataTable']."_id_idx // $sql = "CREATE UNIQUE INDEX ".$CC_CONFIG['mdataTable']."_id_idx
ON ".$CC_CONFIG['mdataTable']." (id)"; // ON ".$CC_CONFIG['mdataTable']." (id)";
camp_install_query($sql, false); // camp_install_query($sql, false);
$sql = "CREATE INDEX ".$CC_CONFIG['mdataTable']."_gunid_idx $sql = "CREATE INDEX ".$CC_CONFIG['mdataTable']."_gunid_idx
ON ".$CC_CONFIG['mdataTable']." (gunid)"; ON ".$CC_CONFIG['mdataTable']." (gunid)";
@ -320,7 +341,7 @@ if (!camp_db_table_exists($CC_CONFIG['transTable'])) {
)"; )";
camp_install_query($sql, false); camp_install_query($sql, false);
$CC_DBC->createSequence($CC_CONFIG['transTable']."_id_seq"); $CC_DBC->createSequence($CC_CONFIG['transSequence']);
$sql = "CREATE UNIQUE INDEX ".$CC_CONFIG['transTable']."_id_idx $sql = "CREATE UNIQUE INDEX ".$CC_CONFIG['transTable']."_id_idx
ON ".$CC_CONFIG['transTable']." (id)"; ON ".$CC_CONFIG['transTable']." (id)";
camp_install_query($sql, false); camp_install_query($sql, false);
@ -350,11 +371,11 @@ if (!camp_db_table_exists($CC_CONFIG['transTable'])) {
if (!camp_db_table_exists($CC_CONFIG['scheduleTable'])) { if (!camp_db_table_exists($CC_CONFIG['scheduleTable'])) {
echo " * Creating database table ".$CC_CONFIG['scheduleTable']."..."; echo " * Creating database table ".$CC_CONFIG['scheduleTable']."...";
$sql = "CREATE TABLE ".$CC_CONFIG['scheduleTable']."(" $sql = "CREATE TABLE ".$CC_CONFIG['scheduleTable']."("
." id BIGINT NOT NULL," ." id BIGINT NOT NULL,"
." playlist BIGINT NOT NULL," ." playlist BIGINT NOT NULL,"
." starts TIMESTAMP NOT NULL," ." starts TIMESTAMP NOT NULL,"
." ends TIMESTAMP NOT NULL," ." ends TIMESTAMP NOT NULL,"
." PRIMARY KEY(id))"; ." PRIMARY KEY(id))";
camp_install_query($sql); camp_install_query($sql);
} else { } else {
echo " * Skipping: database table already exists: ".$CC_CONFIG['scheduleTable']."\n"; echo " * Skipping: database table already exists: ".$CC_CONFIG['scheduleTable']."\n";
@ -364,10 +385,10 @@ if (!camp_db_table_exists($CC_CONFIG['scheduleTable'])) {
if (!camp_db_table_exists($CC_CONFIG['playlogTable'])) { if (!camp_db_table_exists($CC_CONFIG['playlogTable'])) {
echo " * Creating database table ".$CC_CONFIG['playlogTable']."..."; echo " * Creating database table ".$CC_CONFIG['playlogTable']."...";
$sql = "CREATE TABLE ".$CC_CONFIG['playlogTable']."(" $sql = "CREATE TABLE ".$CC_CONFIG['playlogTable']."("
." id BIGINT NOT NULL," ." id BIGINT NOT NULL,"
." audioClipId BIGINT NOT NULL," ." audioClipId BIGINT NOT NULL,"
." timestamp TIMESTAMP NOT NULL," ." timestamp TIMESTAMP NOT NULL,"
." PRIMARY KEY(id))"; ." PRIMARY KEY(id))";
camp_install_query($sql); camp_install_query($sql);
} else { } else {
echo " * Skipping: database table already exists: ".$CC_CONFIG['playlogTable']."\n"; echo " * Skipping: database table already exists: ".$CC_CONFIG['playlogTable']."\n";
@ -377,12 +398,12 @@ if (!camp_db_table_exists($CC_CONFIG['playlogTable'])) {
if (!camp_db_table_exists($CC_CONFIG['backupTable'])) { if (!camp_db_table_exists($CC_CONFIG['backupTable'])) {
echo " * Creating database table ".$CC_CONFIG['backupTable']."..."; echo " * Creating database table ".$CC_CONFIG['backupTable']."...";
$sql = "CREATE TABLE ".$CC_CONFIG['backupTable']." (" $sql = "CREATE TABLE ".$CC_CONFIG['backupTable']." ("
." token VARCHAR(64) NOT NULL," ." token VARCHAR(64) NOT NULL,"
." sessionId VARCHAR(64) NOT NULL," ." sessionId VARCHAR(64) NOT NULL,"
." status VARCHAR(32) NOT NULL," ." status VARCHAR(32) NOT NULL,"
." fromTime TIMESTAMP NOT NULL," ." fromTime TIMESTAMP NOT NULL,"
." toTime TIMESTAMP NOT NULL," ." toTime TIMESTAMP NOT NULL,"
." PRIMARY KEY(token))"; ." PRIMARY KEY(token))";
camp_install_query($sql); camp_install_query($sql);
} else { } else {
echo " * Skipping: database table already exists: ".$CC_CONFIG['backupTable']."\n"; echo " * Skipping: database table already exists: ".$CC_CONFIG['backupTable']."\n";
@ -390,7 +411,7 @@ if (!camp_db_table_exists($CC_CONFIG['backupTable'])) {
if (!camp_db_table_exists($CC_CONFIG['prefTable'])) { if (!camp_db_table_exists($CC_CONFIG['prefTable'])) {
echo " * Creating database table ".$CC_CONFIG['prefTable']."..."; echo " * Creating database table ".$CC_CONFIG['prefTable']."...";
$CC_DBC->createSequence($CC_CONFIG['prefTable']."_id_seq"); //$CC_DBC->createSequence($CC_CONFIG['prefSequence']);
$sql = "CREATE TABLE ".$CC_CONFIG['prefTable']." ( $sql = "CREATE TABLE ".$CC_CONFIG['prefTable']." (
id int not null, id int not null,
subjid int REFERENCES ".$CC_CONFIG['subjTable']." ON DELETE CASCADE, subjid int REFERENCES ".$CC_CONFIG['subjTable']." ON DELETE CASCADE,
@ -478,7 +499,7 @@ $cron = new Cron();
$access = $cron->openCrontab('write'); $access = $cron->openCrontab('write');
if ($access != 'write') { if ($access != 'write') {
do { do {
$r = $cron->forceWriteable(); $r = $cron->forceWriteable();
} while ($r); } while ($r);
} }

View File

@ -20,8 +20,8 @@ echo "***************************\n";
echo "* StorageServer Uninstall *\n"; echo "* StorageServer Uninstall *\n";
echo "***************************\n"; echo "***************************\n";
require_once('../conf.php'); require_once(dirname(__FILE__).'/../conf.php');
require_once('installInit.php'); require_once(dirname(__FILE__).'/installInit.php');
campcaster_db_connect(false); campcaster_db_connect(false);
function camp_uninstall_delete_files($p_path) function camp_uninstall_delete_files($p_path)
@ -47,7 +47,7 @@ if (!PEAR::isError($CC_DBC)) {
$sql = "DROP TABLE ".$CC_CONFIG['prefTable']; $sql = "DROP TABLE ".$CC_CONFIG['prefTable'];
camp_install_query($sql, false); camp_install_query($sql, false);
$CC_DBC->dropSequence($CC_CONFIG['prefTable']."_id_seq"); $CC_DBC->dropSequence($CC_CONFIG['prefTable']."_id");
echo "done.\n"; echo "done.\n";
} else { } else {
echo " * Skipping: database table ".$CC_CONFIG['prefTable']."\n"; echo " * Skipping: database table ".$CC_CONFIG['prefTable']."\n";
@ -88,7 +88,7 @@ if (camp_db_table_exists($CC_CONFIG['transTable'])) {
$sql = "DROP TABLE ".$CC_CONFIG['transTable']; $sql = "DROP TABLE ".$CC_CONFIG['transTable'];
camp_install_query($sql, false); camp_install_query($sql, false);
$CC_DBC->dropSequence($CC_CONFIG['transTable']."_id_seq"); $CC_DBC->dropSequence($CC_CONFIG['transTable']."_id");
echo "done.\n"; echo "done.\n";
} else { } else {
echo " * Skipping: database table ".$CC_CONFIG['transTable']."\n"; echo " * Skipping: database table ".$CC_CONFIG['transTable']."\n";
@ -99,7 +99,7 @@ if (camp_db_table_exists($CC_CONFIG['mdataTable'])) {
$sql = "DROP TABLE ".$CC_CONFIG['mdataTable']; $sql = "DROP TABLE ".$CC_CONFIG['mdataTable'];
camp_install_query($sql, false); camp_install_query($sql, false);
$CC_DBC->dropSequence($CC_CONFIG['mdataTable']."_id_seq"); $CC_DBC->dropSequence($CC_CONFIG['mdataTable']."_id");
echo "done.\n"; echo "done.\n";
} else { } else {
echo " * Skipping: database table ".$CC_CONFIG['mdataTable']."\n"; echo " * Skipping: database table ".$CC_CONFIG['mdataTable']."\n";
@ -109,15 +109,17 @@ if (camp_db_table_exists($CC_CONFIG['filesTable'])) {
echo " * Removing database table ".$CC_CONFIG['filesTable']."..."; echo " * Removing database table ".$CC_CONFIG['filesTable']."...";
$sql = "DROP TABLE ".$CC_CONFIG['filesTable']; $sql = "DROP TABLE ".$CC_CONFIG['filesTable'];
camp_install_query($sql); camp_install_query($sql);
$CC_DBC->dropSequence($CC_CONFIG['filesTable']."_id");
} else { } else {
echo " * Skipping: database table ".$CC_CONFIG['filesTable']."\n"; echo " * Skipping: database table ".$CC_CONFIG['filesTable']."\n";
} }
if (camp_db_sequence_exists($CC_CONFIG['filesSequence'])) { //if (camp_db_sequence_exists($CC_CONFIG['filesSequence'])) {
$sql = "DROP SEQUENCE ".$CC_CONFIG['filesSequence']; // $sql = "DROP SEQUENCE ".$CC_CONFIG['filesSequence'];
camp_install_query($sql); // camp_install_query($sql);
} //}
//
if (camp_db_table_exists($CC_CONFIG['accessTable'])) { if (camp_db_table_exists($CC_CONFIG['accessTable'])) {
echo " * Removing database table ".$CC_CONFIG['accessTable']."..."; echo " * Removing database table ".$CC_CONFIG['accessTable']."...";
$sql = "DROP TABLE ".$CC_CONFIG['accessTable']; $sql = "DROP TABLE ".$CC_CONFIG['accessTable'];
@ -131,7 +133,7 @@ if (camp_db_table_exists($CC_CONFIG['permTable'])) {
$sql = "DROP TABLE ".$CC_CONFIG['permTable']; $sql = "DROP TABLE ".$CC_CONFIG['permTable'];
camp_install_query($sql, false); camp_install_query($sql, false);
$CC_DBC->dropSequence($CC_CONFIG['permTable']."_id_seq"); $CC_DBC->dropSequence($CC_CONFIG['permTable']."_id");
echo "done.\n"; echo "done.\n";
} else { } else {
echo " * Skipping: database table ".$CC_CONFIG['permTable']."\n"; echo " * Skipping: database table ".$CC_CONFIG['permTable']."\n";
@ -147,7 +149,7 @@ if (camp_db_table_exists($CC_CONFIG['sessTable'])) {
if (camp_db_table_exists($CC_CONFIG['subjTable'])) { if (camp_db_table_exists($CC_CONFIG['subjTable'])) {
echo " * Removing database table ".$CC_CONFIG['subjTable']."..."; echo " * Removing database table ".$CC_CONFIG['subjTable']."...";
$CC_DBC->dropSequence($CC_CONFIG['subjTable']."_id_seq"); $CC_DBC->dropSequence($CC_CONFIG['subjTable']."_id");
$sql = "DROP TABLE ".$CC_CONFIG['subjTable']; $sql = "DROP TABLE ".$CC_CONFIG['subjTable'];
camp_install_query($sql, false); camp_install_query($sql, false);
@ -162,7 +164,7 @@ if (camp_db_table_exists($CC_CONFIG['smembTable'])) {
$sql = "DROP TABLE ".$CC_CONFIG['smembTable']; $sql = "DROP TABLE ".$CC_CONFIG['smembTable'];
camp_install_query($sql, false); camp_install_query($sql, false);
$CC_DBC->dropSequence($CC_CONFIG['smembTable']."_id_seq"); $CC_DBC->dropSequence($CC_CONFIG['smembTable']."_id");
echo "done.\n"; echo "done.\n";
} else { } else {
echo " * Skipping: database table ".$CC_CONFIG['smembTable']."\n"; echo " * Skipping: database table ".$CC_CONFIG['smembTable']."\n";

View File

@ -0,0 +1,86 @@
<?php
require_once(dirname(__FILE__).'/../conf.php');
require_once('PHPUnit.php');
require_once('DB.php');
require_once(dirname(__FILE__).'/../StoredFile.php');
require_once(dirname(__FILE__).'/../BasicStor.php');
require_once(dirname(__FILE__).'/../GreenBox.php');
$dsn = $CC_CONFIG['dsn'];
$CC_DBC = DB::connect($dsn, TRUE);
if (PEAR::isError($CC_DBC)) {
echo "ERROR: ".$CC_DBC->getMessage()." ".$CC_DBC->getUserInfo()."\n";
exit(1);
}
$CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
class BasicStorTest extends PHPUnit_TestCase {
private $greenbox;
function __construct($name) {
parent::__construct($name);
}
function setup() {
$this->greenbox = new GreenBox();
}
function testGetAudioMetadata() {
$filePath = dirname(__FILE__)."/ex1.mp3";
$metadata = camp_get_audio_metadata($filePath);
if (PEAR::isError($metadata)) {
$this->fail($metadata->getMessage());
return;
}
if (($metadata["dc:description"] != "Tmu sem tam videla ...")
|| ($metadata["audio"]["dataformat"] != "mp3")
|| ($metadata["dc:type"] != "Speech")) {
$str = " [dc:description] = " . $metadata["dc:description"] ."\n"
. " [audio][dataformat] = " . $metadata["audio"]["dataformat"]."\n"
. " [dc:type] = ".$metadata["dc:type"]."\n";
$this->fail("Metadata has unexpected values:\n".$str);
}
//var_dump($metadata);
}
function testPutFile() {
$STORAGE_SERVER_PATH = dirname(__FILE__)."/../../";
$filePath = dirname(__FILE__)."/ex1.mp3";
$md5sum = md5_file($filePath);
$metadata = camp_get_audio_metadata($filePath);
if (PEAR::isError($metadata)) {
$this->fail($metadata->getMessage());
return;
}
// bsSetMetadataBatch doesnt like these values
unset($metadata['audio']);
unset($metadata['playtime_seconds']);
$values = array(
"filename" => $metadata['ls:filename'],
"filepath" => $filePath,
"metadata" => "$STORAGE_SERVER_PATH/var/emptyMdata.xml",
"gunid" => NULL,
"filetype" => "audioclip",
"md5" => $md5sum,
"mime" => $metadata['dc:format']
);
$storedFile = $this->greenbox->bsPutFile($values, false);
$this->assertFalse(PEAR::isError($storedFile));
$id = $storedFile->getId();
if (!is_numeric($id)) {
$this->fail("StoredFile not created correctly. id = ".$id);
return;
}
$r = $this->greenbox->bsSetMetadataBatch($storedFile, $metadata);
if (PEAR::isError($r)) {
$this->fail($r->getMessage());
//echo var_export($metadata)."\n";
return;
}
}
}
?>

View File

@ -0,0 +1,9 @@
<?php
require_once 'UnitTests.php';
$suite = new PHPUnit_TestSuite("BasicStorTest");
$result = PHPUnit::run($suite);
echo $result->toString();
?>

View File

@ -1,6 +1,4 @@
<?php <?php
$WHITE_SCREEN_OF_DEATH = false;
header("Content-type: text/plain"); header("Content-type: text/plain");
require_once('../conf.php'); require_once('../conf.php');

View File

@ -0,0 +1,132 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* PHP Version 4
*
* Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: PHPUnit.php,v 1.17 2005/11/10 09:47:11 sebastian Exp $
* @link http://pear.php.net/package/PHPUnit
* @since File available since Release 1.0.0
*/
require_once 'PHPUnit/TestCase.php';
require_once 'PHPUnit/TestResult.php';
require_once 'PHPUnit/TestSuite.php';
/**
* PHPUnit runs a TestSuite and returns a TestResult object.
*
* Here is an example:
*
* <code>
* <?php
* require_once 'PHPUnit.php';
*
* class MathTest extends PHPUnit_TestCase {
* var $fValue1;
* var $fValue2;
*
* function MathTest($name) {
* $this->PHPUnit_TestCase($name);
* }
*
* function setUp() {
* $this->fValue1 = 2;
* $this->fValue2 = 3;
* }
*
* function testAdd() {
* $this->assertTrue($this->fValue1 + $this->fValue2 == 5);
* }
* }
*
* $suite = new PHPUnit_TestSuite();
* $suite->addTest(new MathTest('testAdd'));
*
* $result = PHPUnit::run($suite);
* print $result->toHTML();
* ?>
* </code>
*
* Alternatively, you can pass a class name to the PHPUnit_TestSuite()
* constructor and let it automatically add all methods of that class
* that start with 'test' to the suite:
*
* <code>
* <?php
* $suite = new PHPUnit_TestSuite('MathTest');
* $result = PHPUnit::run($suite);
* print $result->toHTML();
* ?>
* </code>
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PHPUnit
* @since Class available since Release 1.0.0
*/
class PHPUnit {
/**
* Runs a test(suite).
*
* @param mixed
* @return PHPUnit_TestResult
* @access public
*/
function &run(&$suite) {
$result = new PHPUnit_TestResult();
$suite->run($result);
return $result;
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>

View File

@ -0,0 +1,426 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* PHP Version 4
*
* Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: Assert.php,v 1.29 2005/11/10 09:47:14 sebastian Exp $
* @link http://pear.php.net/package/PHPUnit
* @since File available since Release 1.0.0
*/
/**
* A set of assert methods.
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PHPUnit
* @since Class available since Release 1.0.0
*/
class PHPUnit_Assert {
/**
* @var boolean
* @access private
*/
var $_looselyTyped = FALSE;
/**
* Asserts that a haystack contains a needle.
*
* @param mixed
* @param mixed
* @param string
* @access public
* @since Method available since Release 1.1.0
*/
function assertContains($needle, $haystack, $message = '') {
if (is_string($needle) && is_string($haystack)) {
$this->assertTrue(strpos($haystack, $needle) !== FALSE, $message);
}
else if (is_array($haystack) && !is_object($needle)) {
$this->assertTrue(in_array($needle, $haystack), $message);
}
else {
$this->fail('Unsupported parameter passed to assertContains().');
}
}
/**
* Asserts that a haystack does not contain a needle.
*
* @param mixed
* @param mixed
* @param string
* @access public
* @since Method available since Release 1.1.0
*/
function assertNotContains($needle, $haystack, $message = '') {
if (is_string($needle) && is_string($haystack)) {
$this->assertFalse(strpos($haystack, $needle) !== FALSE, $message);
}
else if (is_array($haystack) && !is_object($needle)) {
$this->assertFalse(in_array($needle, $haystack), $message);
}
else {
$this->fail('Unsupported parameter passed to assertNotContains().');
}
}
/**
* Asserts that two variables are equal.
*
* @param mixed
* @param mixed
* @param string
* @param mixed
* @access public
*/
function assertEquals($expected, $actual, $message = '', $delta = 0) {
if ((is_array($actual) && is_array($expected)) ||
(is_object($actual) && is_object($expected))) {
if (is_array($actual) && is_array($expected)) {
ksort($actual);
ksort($expected);
}
if ($this->_looselyTyped) {
$actual = $this->_convertToString($actual);
$expected = $this->_convertToString($expected);
}
$actual = serialize($actual);
$expected = serialize($expected);
$message = sprintf(
'%sexpected %s, actual %s',
!empty($message) ? $message . ' ' : '',
$expected,
$actual
);
if ($actual !== $expected) {
return $this->fail($message);
}
}
elseif (is_numeric($actual) && is_numeric($expected)) {
$message = sprintf(
'%sexpected %s%s, actual %s',
!empty($message) ? $message . ' ' : '',
$expected,
($delta != 0) ? ('+/- ' . $delta) : '',
$actual
);
if (!($actual >= ($expected - $delta) && $actual <= ($expected + $delta))) {
return $this->fail($message);
}
}
else {
$message = sprintf(
'%sexpected %s, actual %s',
!empty($message) ? $message . ' ' : '',
$expected,
$actual
);
if ($actual !== $expected) {
return $this->fail($message);
}
}
}
/**
* Asserts that two variables reference the same object.
* This requires the Zend Engine 2 to work.
*
* @param object
* @param object
* @param string
* @access public
* @deprecated
*/
function assertSame($expected, $actual, $message = '') {
if (!version_compare(phpversion(), '5.0.0', '>=')) {
$this->fail('assertSame() only works with PHP >= 5.0.0.');
}
if ((is_object($expected) || is_null($expected)) &&
(is_object($actual) || is_null($actual))) {
$message = sprintf(
'%sexpected two variables to reference the same object',
!empty($message) ? $message . ' ' : ''
);
if ($expected !== $actual) {
return $this->fail($message);
}
} else {
$this->fail('Unsupported parameter passed to assertSame().');
}
}
/**
* Asserts that two variables do not reference the same object.
* This requires the Zend Engine 2 to work.
*
* @param object
* @param object
* @param string
* @access public
* @deprecated
*/
function assertNotSame($expected, $actual, $message = '') {
if (!version_compare(phpversion(), '5.0.0', '>=')) {
$this->fail('assertNotSame() only works with PHP >= 5.0.0.');
}
if ((is_object($expected) || is_null($expected)) &&
(is_object($actual) || is_null($actual))) {
$message = sprintf(
'%sexpected two variables to reference different objects',
!empty($message) ? $message . ' ' : ''
);
if ($expected === $actual) {
return $this->fail($message);
}
} else {
$this->fail('Unsupported parameter passed to assertNotSame().');
}
}
/**
* Asserts that a variable is not NULL.
*
* @param mixed
* @param string
* @access public
*/
function assertNotNull($actual, $message = '') {
$message = sprintf(
'%sexpected NOT NULL, actual NULL',
!empty($message) ? $message . ' ' : ''
);
if (is_null($actual)) {
return $this->fail($message);
}
}
/**
* Asserts that a variable is NULL.
*
* @param mixed
* @param string
* @access public
*/
function assertNull($actual, $message = '') {
$message = sprintf(
'%sexpected NULL, actual NOT NULL',
!empty($message) ? $message . ' ' : ''
);
if (!is_null($actual)) {
return $this->fail($message);
}
}
/**
* Asserts that a condition is true.
*
* @param boolean
* @param string
* @access public
*/
function assertTrue($condition, $message = '') {
$message = sprintf(
'%sexpected TRUE, actual FALSE',
!empty($message) ? $message . ' ' : ''
);
if (!$condition) {
return $this->fail($message);
}
}
/**
* Asserts that a condition is false.
*
* @param boolean
* @param string
* @access public
*/
function assertFalse($condition, $message = '') {
$message = sprintf(
'%sexpected FALSE, actual TRUE',
!empty($message) ? $message . ' ' : ''
);
if ($condition) {
return $this->fail($message);
}
}
/**
* Asserts that a string matches a given regular expression.
*
* @param string
* @param string
* @param string
* @access public
*/
function assertRegExp($pattern, $string, $message = '') {
$message = sprintf(
'%s"%s" does not match pattern "%s"',
!empty($message) ? $message . ' ' : '',
$string,
$pattern
);
if (!preg_match($pattern, $string)) {
return $this->fail($message);
}
}
/**
* Asserts that a string does not match a given regular expression.
*
* @param string
* @param string
* @param string
* @access public
* @since Method available since Release 1.1.0
*/
function assertNotRegExp($pattern, $string, $message = '') {
$message = sprintf(
'%s"%s" matches pattern "%s"',
!empty($message) ? $message . ' ' : '',
$string,
$pattern
);
if (preg_match($pattern, $string)) {
return $this->fail($message);
}
}
/**
* Asserts that a variable is of a given type.
*
* @param string $expected
* @param mixed $actual
* @param optional string $message
* @access public
*/
function assertType($expected, $actual, $message = '') {
return $this->assertEquals(
$expected,
gettype($actual),
$message
);
}
/**
* Converts a value to a string.
*
* @param mixed $value
* @access private
*/
function _convertToString($value) {
foreach ($value as $k => $v) {
if (is_array($v)) {
$value[$k] = $this->_convertToString($value[$k]);
} else {
settype($value[$k], 'string');
}
}
return $value;
}
/**
* @param boolean $looselyTyped
* @access public
*/
function setLooselyTyped($looselyTyped) {
if (is_bool($looselyTyped)) {
$this->_looselyTyped = $looselyTyped;
}
}
/**
* Fails a test with the given message.
*
* @param string
* @access protected
* @abstract
*/
function fail($message = '') { /* abstract */ }
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>

View File

@ -0,0 +1,740 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* PHP Version 4
*
* Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package PHPUnit
* @author Scott Mattocks <scott@crisscott.com>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: Gtk.php,v 1.6 2005/11/10 09:47:15 sebastian Exp $
* @link http://pear.php.net/package/PHPUnit
* @since File available since Release 1.2.0
*/
if (!function_exists('is_a')) {
require_once 'PHP/Compat/Function/is_a.php';
}
/**
* GTK GUI interface for PHPUnit.
*
* This class is a PHP port of junit.awtui.testrunner. Documentation
* for junit.awtui.testrunner can be found at
* http://junit.sourceforge.net
*
* Due to the limitations of PHP4 and PHP-Gtk, this class can not
* duplicate all of the functionality of the JUnit GUI. Some of the
* things this class cannot do include:
* - Reloading the class for each run
* - Stopping the test in progress
*
* To use simply intantiate the class and call main()
* $gtk =& new PHPUnit_GUI_Gtk;
* $gtk->main();
*
* Once the window has finished loading, you can enter the name of
* a class that has been loaded (include/require some where in your
* code, or you can pass the name of the file containing the class.
*
* You can also load classes using the SetupDecorator class.
* require_once 'PHPUnit/GUI/SetupDecorator.php';
* require_once 'PHPUnit/GUI/Gtk.php';
* $gui = new PHPUnit_GUI_SetupDecorator(new PHPUnit_GUI_Gtk());
* $gui->getSuitesFromDir('/path/to/test','.*\.php$',array('index.php','sql.php'));
* $gui->show();
*
*
* @category Testing
* @package PHPUnit
* @author Scott Mattocks <scott@crisscott.com>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PHPUnit
* @since Class available since Release 1.2.0
* @todo Allow file drop. (Gtk_FileDrop)
*/
class PHPUnit_GUI_Gtk {
/**
* The main gtk window
* @var object
*/
var $gui;
/**
* The text entry that contains the name of the
* file that holds the test(s)/suite(s).
* @var object
*/
var $suiteField;
/**
* The label that shows the number of tests that
* were run.
* @var object
*/
var $numberOfRuns;
/**
* The label that shows the number of errors that
* were encountered.
* @var object
*/
var $numberOfErrors;
/**
* The label that shows the number of failures
* that were encountered.
* @var object
*/
var $numberOfFailures;
/**
* The label for reporting user messages.
* @var object
*/
var $statusLine;
/**
* The text area for reporting messages from successful
* test runs. (not necessarily successful tests)
* @var object
*/
var $reportArea;
/**
* The text area for reporting errors encountered when
* running tests.
* @var object
*/
var $dumpArea;
/**
* The progress bar indicator. Shows the percentage of
* passed tests.
* @var object
*/
var $progress;
/**
* A checkbox for the user to indicate whether or not they
* would like to see results from all tests or just failures.
* @object
*/
var $showPassed;
/**
* Constructor.
*
* The constructor checks for the gtk extension and loads it
* if needed. Then it creates the GUI. The GUI is not shown
* nor is the main gtk loop started until main() is called.
*
* @access public
* @param none
* @return void
*/
function PHPUnit_GUI_Gtk()
{
// Check for php-gtk extension.
if (!extension_loaded('gtk')) {
dl( 'php_gtk.' . PHP_SHLIB_SUFFIX);
}
// Create the interface but don't start the loop
$this->_createUI();
}
/**
* Start the main gtk loop.
*
* main() first sets the default state of the showPassed
* check box. Next all widgets that are part of the GUI
* are shown. Finally the main gtk loop is started.
*
* @access public
* @param boolean $showPassed
* @return void
*/
function main($showPassed = true)
{
$this->showPassed->set_active($showPassed);
$this->gui->show_all();
gtk::main();
}
/**
* Create the user interface.
*
* The user interface is pretty simple. It consists of a
* menu, text entry, run button, some labels, a progress
* indicator, and a couple of areas for notification of
* any messages.
*
* @access private
* @param none
* @return void
*/
function _createUI()
{
// Create a window.
$window =& new GtkWindow;
$window->set_title('PHPUnit Gtk');
$window->set_usize(400, -1);
// Create the main box.
$mainBox =& new GtkVBox;
$window->add($mainBox);
// Start with the menu.
$mainBox->pack_start($this->_createMenu());
// Then add the suite field entry.
$mainBox->pack_start($this->_createSuiteEntry());
// Then add the report labels.
$mainBox->pack_start($this->_createReportLabels());
// Next add the progress bar.
$mainBox->pack_start($this->_createProgressBar());
// Then add the report area and the dump area.
$mainBox->pack_start($this->_createReportAreas());
// Finish off with the status line.
$mainBox->pack_start($this->_createStatusLine());
// Connect the destroy signal.
$window->connect_object('destroy', array('gtk', 'main_quit'));
// Assign the member.
$this->gui =& $window;
}
/**
* Create the menu.
*
* The menu is very simple. It an exit menu item, which exits
* the application, and an about menu item, which shows some
* basic information about the application itself.
*
* @access private
* @param none
* @return &object The GtkMenuBar
*/
function &_createMenu()
{
// Create the menu bar.
$menuBar =& new GtkMenuBar;
// Create the main (only) menu item.
$phpHeader =& new GtkMenuItem('PHPUnit');
// Add the menu item to the menu bar.
$menuBar->append($phpHeader);
// Create the PHPUnit menu.
$phpMenu =& new GtkMenu;
// Add the menu items
$about =& new GtkMenuItem('About...');
$about->connect('activate', array(&$this, 'about'));
$phpMenu->append($about);
$exit =& new GtkMenuItem('Exit');
$exit->connect_object('activate', array('gtk', 'main_quit'));
$phpMenu->append($exit);
// Complete the menu.
$phpHeader->set_submenu($phpMenu);
return $menuBar;
}
/**
* Create the suite entry and related widgets.
*
* The suite entry has some supporting components such as a
* label, the show passed check box and the run button. All
* of these items are packed into two nested boxes.
*
* @access private
* @param none
* @return &object A box that contains all of the suite entry pieces.
*/
function &_createSuiteEntry()
{
// Create the outermost box.
$outerBox =& new GtkVBox;
// Create the suite label, box, and field.
$suiteLabel =& new GtkLabel('Test class name:');
$suiteBox =& new GtkHBox;
$this->suiteField =& new GtkEntry;
$this->suiteField->set_text($suiteName != NULL ? $suiteName : '');
// Create the button the user will use to start the test.
$runButton =& new GtkButton('Run');
$runButton->connect_object('clicked', array(&$this, 'run'));
// Create the check box that lets the user show only failures.
$this->showPassed =& new GtkCheckButton('Show passed tests');
// Add the components to their respective boxes.
$suiteLabel->set_alignment(0, 0);
$outerBox->pack_start($suiteLabel);
$outerBox->pack_start($suiteBox);
$outerBox->pack_start($this->showPassed);
$suiteBox->pack_start($this->suiteField);
$suiteBox->pack_start($runButton);
return $outerBox;
}
/**
* Create the labels that tell the user what has happened.
*
* There are three labels, one each for total runs, errors and
* failures. There is also one label for each of these that
* describes what the label is. It could be done with one label
* instead of two but that would make updates much harder.
*
* @access private
* @param none
* @return &object A box containing the labels.
*/
function &_createReportLabels()
{
// Create a box to hold everything.
$labelBox =& new GtkHBox;
// Create the non-updated labels.
$numberOfRuns =& new GtkLabel('Runs:');
$numberOfErrors =& new GtkLabel('Errors:');
$numberOfFailures =& new GtkLabel('Failures:');
// Create the labels that will be updated.
// These are asssigned to members to make it easier to
// set their values later.
$this->numberOfRuns =& new GtkLabel(0);
$this->numberOfErrors =& new GtkLabel(0);
$this->numberOfFailures =& new GtkLabel(0);
// Pack everything in.
$labelBox->pack_start($numberOfRuns);
$labelBox->pack_start($this->numberOfRuns);
$labelBox->pack_start($numberOfErrors);
$labelBox->pack_start($this->numberOfErrors);
$labelBox->pack_start($numberOfFailures);
$labelBox->pack_start($this->numberOfFailures);
return $labelBox;
}
/**
* Create the success/failure indicator.
*
* A GtkProgressBar is used to visually indicate how many
* tests were successful compared to how many were not. The
* progress bar shows the percentage of success and will
* change from green to red if there are any failures.
*
* @access private
* @param none
* @return &object The progress bar
*/
function &_createProgressBar()
{
// Create the progress bar.
$this->progress =& new GtkProgressBar(new GtkAdjustment(0, 0, 1, .1, 1, 0));
// Set the progress bar to print the percentage.
$this->progress->set_show_text(true);
return $this->progress;
}
/**
* Create the report text areas.
*
* The report area consists of one text area for failures, one
* text area for errors and one label for identification purposes.
* All three widgets are packed into a box.
*
* @access private
* @param none
* @return &object The box containing the report areas.
*/
function &_createReportAreas()
{
// Create the containing box.
$reportBox =& new GtkVBox;
// Create the identification label
$reportLabel =& new GtkLabel('Errors and Failures:');
$reportLabel->set_alignment(0, 0);
// Create the scrolled windows for the text areas.
$reportScroll =& new GtkScrolledWindow;
$dumpScroll =& new GtkScrolledWindow;
// Make the scroll areas big enough.
$reportScroll->set_usize(-1, 150);
$dumpScroll->set_usize(-1, 150);
// Only show the vertical scroll bar when needed.
// Never show the horizontal scroll bar.
$reportScroll->set_policy(GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
$dumpScroll->set_policy(GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
// Create the text areas.
$this->reportArea =& new GtkText;
$this->dumpArea =& new GtkText;
// Don't let words get broken.
$this->reportArea->set_word_wrap(true);
$this->dumpArea->set_word_wrap(true);
// Pack everything in.
$reportBox->pack_start($reportLabel);
$reportScroll->add($this->reportArea);
$reportBox->pack_start($reportScroll);
$dumpScroll->add($this->dumpArea);
$reportBox->pack_start($dumpScroll);
return $reportBox;
}
/**
* Create a status label.
*
* A status line at the bottom of the application is used
* to notify the user of non-test related messages such as
* failures loading a test suite.
*
* @access private
* @param none
* @return &object The status label.
*/
function &_createStatusLine()
{
// Create the status label.
$this->statusLine =& new GtkLabel('');
$this->statusLine->set_alignment(0, 0);
return $this->statusLine;
}
/**
* Show a popup with information about the application.
*
* The popup should show information about the version,
* the author, the license, where to get the latest
* version and a short description.
*
* @access public
* @param none
* @return void
*/
function about()
{
// Create the new window.
$about =& new GtkWindow;
$about->set_title('About PHPUnit GUI Gtk');
$about->set_usize(250, -1);
// Put two vboxes in the hbox.
$vBox =& new GtkVBox;
$about->add($vBox);
// Create the labels.
$version =& new GtkLabel(" Version: 1.0");
$license =& new GtkLabel(" License: PHP License v3.0");
$where =& new GtkLabel(" Download from: http://pear.php.net/PHPUnit/");
$unitAuth =& new GtkLabel(" PHPUnit Author: Sebastian Bergman");
$gtkAuth =& new GtkLabel(" Gtk GUI Author: Scott Mattocks");
// Align everything to the left
$where->set_alignment(0, .5);
$version->set_alignment(0, .5);
$license->set_alignment(0, .5);
$gtkAuth->set_alignment(0, .5);
$unitAuth->set_alignment(0, .5);
// Pack everything into the vBox;
$vBox->pack_start($version);
$vBox->pack_start($license);
$vBox->pack_start($where);
$vBox->pack_start($unitAuth);
$vBox->pack_start($gtkAuth);
// Connect the destroy signal.
$about->connect('destroy', array('gtk', 'true'));
// Show the goods.
$about->show_all();
}
/**
* Load the test suite.
*
* This method tries to load test suite based on the user
* info. If the user passes the name of a tests suite, it
* is instantiated and a new object is returned. If the
* user passes a file that contains a test suite, the class
* is instantiated and a new object is returned. If the user
* passes a file that contains a test case, the test case is
* passed to a new test suite and the new suite object is
* returned.
*
* @access public
* @param string The file that contains a test case/suite or the classname.
* @return &object The new test suite.
*/
function &loadTest(&$file)
{
// Check to see if a class name was given.
if (is_a($file, 'PHPUnit_TestSuite')) {
return $file;
} elseif (class_exists($file)) {
require_once 'PHPUnit/TestSuite.php';
return new PHPUnit_TestSuite($file);
}
// Check that the file exists.
if (!@is_readable($file)) {
$this->_showStatus('Cannot find file: ' . $file);
return false;
}
$this->_showStatus('Loading test suite...');
// Instantiate the class.
// If the path is /path/to/test/TestClass.php
// the class name should be test_TestClass
require_once $file;
$className = str_replace(DIRECTORY_SEPARATOR, '_', $file);
$className = substr($className, 0, strpos($className, '.'));
require_once 'PHPUnit/TestSuite.php';
return new PHPUnit_TestSuite($className);
}
/**
* Run the test suite.
*
* This method runs the test suite and updates the messages
* for the user. When finished it changes the status line
* to 'Test Complete'
*
* @access public
* @param none
* @return void
*/
function runTest()
{
// Notify the user that the test is running.
$this->_showStatus('Running Test...');
// Run the test.
$result = PHPUnit::run($this->suite);
// Update the labels.
$this->_setLabelValue($this->numberOfRuns, $result->runCount());
$this->_setLabelValue($this->numberOfErrors, $result->errorCount());
$this->_setLabelValue($this->numberOfFailures, $result->failureCount());
// Update the progress bar.
$this->_updateProgress($result->runCount(),
$result->errorCount(),
$result->failureCount()
);
// Show the errors.
$this->_showFailures($result->errors(), $this->dumpArea);
// Show the messages from the tests.
if ($this->showPassed->get_active()) {
// Show failures and success.
$this->_showAll($result, $this->reportArea);
} else {
// Show only failures.
$this->_showFailures($result->failures(), $this->reportArea);
}
// Update the status message.
$this->_showStatus('Test complete');
}
/**
* Set the text of a label.
*
* Change the text of a given label.
*
* @access private
* @param widget &$label The label whose value is to be changed.
* @param string $value The new text of the label.
* @return void
*/
function _setLabelValue(&$label, $value)
{
$label->set_text($value);
}
/**
* The main work of the application.
*
* Load the test suite and then execute the tests.
*
* @access public
* @param none
* @return void
*/
function run()
{
// Load the test suite.
$this->suite =& $this->loadTest($this->suiteField->get_text());
// Check to make sure the suite was loaded properly.
if (!is_object($this->suite)) {
// Raise an error.
$this->_showStatus('Could not load test suite.');
return false;
}
// Run the tests.
$this->runTest();
}
/**
* Update the status message.
*
* @access private
* @param string $status The new message.
* @return void
*/
function _showStatus($status)
{
$this->statusLine->set_text($status);
}
/**
* Alias for main()
*
* @see main
*/
function show($showPassed = true)
{
$this->main($showPassed);
}
/**
* Add a suite to the tests.
*
* This method is require by SetupDecorator. It adds a
* suite to the the current set of suites.
*
* @access public
* @param object $testSuite The suite to add.
* @return void
*/
function addSuites($testSuite)
{
if (!is_array($testSuite)) {
settype($testSuite, 'array');
}
foreach ($testSuite as $suite) {
if (is_a($this->suite, 'PHPUnit_TestSuite')) {
$this->suite->addTestSuite($suite->getName());
} else {
$this->suite =& $this->loadTest($suite);
}
// Set the suite field.
$text = $this->suiteField->get_text();
if (empty($text)) {
$this->suiteField->set_text($this->suite->getName());
}
}
}
/**
* Show all test messages.
*
* @access private
* @param object The TestResult from the test suite.
* @return void
*/
function _showAll(&$result)
{
// Clear the area first.
$this->reportArea->delete_text(0, -1);
$this->reportArea->insert_text($result->toString(), 0);
}
/**
* Show failure/error messages in the given text area.
*
* @access private
* @param object &$results The results of the test.
* @param widget &$area The area to show the results in.
*/
function _showFailures(&$results, &$area)
{
$area->delete_text(0, -1);
foreach (array_reverse($results, true) as $result) {
$area->insert_text($result->toString(), 0);
}
}
/**
* Update the progress indicator.
*
* @access private
* @param integer $runs
* @param integer $errors
* @param integer $failures
* @return void
*/
function _updateProgress($runs, $errors, $failures)
{
$percentage = 1 - (($errors + $failures) / $runs);
$this->progress->set_percentage($percentage);
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>

View File

@ -0,0 +1,252 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* PHP Version 4
*
* Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package PHPUnit
* @author Wolfram Kriesing <wolfram@kriesing.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: HTML.php,v 1.19 2005/11/10 09:47:15 sebastian Exp $
* @link http://pear.php.net/package/PHPUnit
* @since File available since Release 1.0.0
*/
/**
* HTML GUI.
*
* @category Testing
* @package PHPUnit
* @author Wolfram Kriesing <wolfram@kriesing.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PHPUnit
* @since Class available since Release 1.0.0
*/
class PHPUnit_GUI_HTML
{
var $_suites = array();
/**
* the current implementation of PHPUnit is designed
* this way that adding a suite to another suite only
* grabs all the tests and adds them to the suite, so you
* have no chance to find out which test goes with which suite
* therefore you can simply pass an array of suites to this constructor here
*
* @param array The suites to be tested. If not given, then you might
* be using the SetupDecorator, which detects them automatically
* when calling getSuitesFromDir()
*/
function PHPUnit_GUI_HTML($suites = array())
{
if (!is_array($suites)) {
$this->_suites = array($suites);
} else {
$this->_suites = $suites;
}
}
/**
* Add suites to the GUI
*
* @param object this should be an instance of PHPUnit_TestSuite
*/
function addSuites($suites)
{
$this->_suites = array_merge($this->_suites,$suites);
}
/**
* this prints the HTML code straight out
*
*/
function show()
{
$request = $_REQUEST;
$showPassed = FALSE;
$submitted = @$request['submitted'];
if ($submitted) {
$showPassed = @$request['showOK'] ? TRUE : FALSE;
}
$suiteResults = array();
foreach ($this->_suites as $aSuite) {
$aSuiteResult = array();
// remove the first directory's name from the test-suite name, since it
// mostly is something like 'tests' or alike
$removablePrefix = explode('_',$aSuite->getName());
$aSuiteResult['name'] = str_replace($removablePrefix[0].'_', '', $aSuite->getName());
if ($submitted && isset($request[$aSuiteResult['name']])) {
$result = PHPUnit::run($aSuite);
$aSuiteResult['counts']['run'] = $result->runCount();
$aSuiteResult['counts']['error'] = $result->errorCount();
$aSuiteResult['counts']['failure'] = $result->failureCount();
$aSuiteResult['results'] = $this->_prepareResult($result,$showPassed);
$per = 100/$result->runCount();
$failed = ($per*$result->errorCount())+($per*$result->failureCount());
$aSuiteResult['percent'] = round(100-$failed,2);
} else {
$aSuiteResult['addInfo'] = 'NOT EXECUTED';
}
$suiteResults[] = $aSuiteResult;
}
$final['name'] = 'OVERALL RESULT';
$final['counts'] = array();
$final['percent'] = 0;
$numExecutedTests = 0;
foreach ($suiteResults as $aSuiteResult) {
if (sizeof(@$aSuiteResult['counts'])) {
foreach ($aSuiteResult['counts'] as $key=>$aCount) {
if (!isset($final['counts'][$key])) {
$final['counts'][$key] = 0;
}
$final['counts'][$key] += $aCount;
}
}
}
if (isset($final['counts']['run'])) {
$per = 100/$final['counts']['run'];
$failed = ($per*$final['counts']['error'])+($per*$final['counts']['failure']);
$final['percent'] = round(100-$failed,2);
} else {
$final['percent'] = 0;
}
array_unshift($suiteResults,$final);
include 'PHPUnit/GUI/HTML.tpl';
}
function _prepareResult($result,$showPassed)
{
$ret = array();
$failures = $result->failures();
foreach($failures as $aFailure) {
$ret['failures'][] = $this->_prepareFailure($aFailure);
}
$errors = $result->errors();
foreach($errors as $aError) {
$ret['errors'][] = $this->_prepareErrors($aError);
}
if ($showPassed) {
$passed = $result->passedTests();
foreach($passed as $aPassed) {
$ret['passed'][] = $this->_preparePassedTests($aPassed);
}
}
return $ret;
}
function _prepareFailure($failure)
{
$test = $failure->failedTest();
$ret['testName'] = $test->getName();
$exception = $failure->thrownException();
// a serialized string starts with a 'character:decimal:{'
// if so we try to unserialize it
// this piece of the regular expression is for detecting a serialized
// type like 'a:3:' for an array with three element or an object i.e. 'O:12:"class":3'
$serialized = '(\w:\d+:(?:"[^"]+":\d+:)?\{.*\})';
// Spaces might make a diff, so we shall show them properly (since a
// user agent ignores them).
if (preg_match('/^(.*)expected ' . $serialized . ', actual ' . $serialized . '$/sU', $exception, $matches)) {
ob_start();
print_r(unserialize($matches[2]));
$ret['expected'] = htmlspecialchars($matches[1]) . "<pre>" . htmlspecialchars(rtrim(ob_get_contents())) . "</pre>";
// Improved compatibility, ob_clean() would be PHP >= 4.2.0 only.
ob_end_clean();
ob_start();
print_r(unserialize($matches[3]));
$ret['actual'] = htmlspecialchars($matches[1]) . "<pre>" . htmlspecialchars(rtrim(ob_get_contents())) . "</pre>";
ob_end_clean();
}
else if (preg_match('/^(.*)expected (.*), actual (.*)$/sU', $exception, $matches)) {
$ret['expected'] = nl2br(str_replace(" ", "&nbsp;", htmlspecialchars($matches[1] . $matches[2])));
$ret['actual'] = nl2br(str_replace(" ", "&nbsp;", htmlspecialchars($matches[1] . $matches[3])));
} else {
$ret['message'] = nl2br(str_replace(" ", "&nbsp;", htmlspecialchars($exception)));
}
return $ret;
}
function _preparePassedTests($passed)
{
$ret['testName'] = $passed->getName();
return $ret;
}
function _prepareError($error)
{
$ret['testName'] = $error->getName();
$ret['message'] = $error->toString();
return $ret;
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>

View File

@ -0,0 +1,156 @@
<html>
<head>
<STYLE type="text/css">
body, td {
background-color: lightgrey;
}
table.outline, outlineFailure {
background-color: black;
border-width: 1px;
}
td {
padding: 2px;
}
th {
text-align: left;
color: white;
background-color: black;
}
.success {
background-color: lightgreen;
}
.failure {
background-color: orange;
}
.info {
padding: 2px;
color: orange;
}
</STYLE>
</head>
<body>
<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="post" name="optionsForm">
<table align="center" class="outline" width="70%">
<tr>
<th colspan="10">
Options
</th>
</tr>
<tr>
<td colspan="10">
<input type="checkbox" onClick="unCheckAll()" name="allChecked">
(un)check all
&nbsp; &nbsp;
show OK <input type="checkbox" name="showOK" <?php echo @$request['showOK']?'checked':''?>>
&nbsp; &nbsp;
<input type="submit" name="submitted" value="run tests">
</td>
</tr>
<?php foreach($suiteResults as $aResult): ?>
<tr>
<th colspan="10">
<input type="checkbox" name="<?php echo $aResult['name'] ?>" <?php echo @$request[$aResult['name']]?'checked':'' ?>>
<?php echo $aResult['name'] ?>
&nbsp;
<?php if (isset($aResult['addInfo'])): ?>
<font class="info"><?php echo @$aResult['addInfo'] ?></font>
<?php endif ?>
</th>
</tr>
<?php if(@$aResult['percent']): ?>
<tr>
<td colspan="10" nowrap="nowrap">
<table style="width:100%; padding:2px;" cellspacing="0" cellspan="0" cellpadding="0">
<tr>
<td width="<?php echo $aResult['percent'] ?>%" class="success" align="center" style="padding:0;">
<?php echo $aResult['percent']?$aResult['percent'].'%':'' ?>
</td>
<td width="<?php echo 100-$aResult['percent'] ?>%" class="failure" align="center" style="padding:0;">
<?php echo (100-$aResult['percent'])?(100-$aResult['percent'].'%'):'' ?>
</td>
</tr>
</table>
</td>
</tr>
<?php endif ?>
<?php if(@$aResult['counts']): ?>
<tr>
<td colspan="10">
<?php foreach($aResult['counts'] as $aCount=>$value): ?>
<?php echo $aCount ?>s = <?php echo $value ?> &nbsp; &nbsp; &nbsp; &nbsp;
<?php endforeach ?>
</td>
</tr>
<?php endif ?>
<?php if(isset($aResult['results']['failures']) && sizeof($aResult['results']['failures']))
foreach($aResult['results']['failures'] as $aFailure): ?>
<tr>
<td class="failure"><?php echo $aFailure['testName'] ?></td>
<td class="failure">
<?php if(isset($aFailure['message']) && $aFailure['message']): ?>
<?php echo $aFailure['message'] ?>
<?php else: ?>
<table class="outlineFailure">
<tr>
<td>expected</td>
<td><?php echo $aFailure['expected'] ?></td>
</tr>
<tr>
<td>actual</td>
<td><?php echo $aFailure['actual'] ?></td>
</tr>
</table>
<?php endif ?>
</td>
</tr>
<?php endforeach ?>
<?php if(isset($aResult['results']['errors']) && sizeof($aResult['results']['errors']))
foreach($aResult['results']['errors'] as $aError): ?>
<tr>
<td class="failure"><?php echo $aError['testName'] ?></td>
<td class="failure">
<?php echo $aError['message'] ?>
</td>
</tr>
<?php endforeach ?>
<?php if(isset($aResult['results']['passed']) && sizeof($aResult['results']['passed']))
foreach($aResult['results']['passed'] as $aPassed): ?>
<tr>
<td class="success"><?php echo $aPassed['testName'] ?></td>
<td class="success"><b>OK</b></td>
</tr>
<?php endforeach ?>
<?php endforeach ?>
</table>
</form>
<script>
var allSuiteNames = new Array();
<?php foreach($suiteResults as $aResult): ?>
allSuiteNames[allSuiteNames.length] = "<?php echo $aResult['name'] ?>";
<?php endforeach ?>
function unCheckAll()
{
_checked = document.optionsForm.allChecked.checked;
for (i=0;i<allSuiteNames.length;i++) {
document.optionsForm[allSuiteNames[i]].checked = _checked;
}
}
</script>
</body>
</html>

View File

@ -0,0 +1,209 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* PHP Version 4
*
* Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package PHPUnit
* @author Wolfram Kriesing <wolfram@kriesing.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: SetupDecorator.php,v 1.15 2005/11/10 09:47:15 sebastian Exp $
* @link http://pear.php.net/package/PHPUnit
* @since File available since Release 1.0.0
*/
/**
* This decorator actually just adds the functionality to read the
* test-suite classes from a given directory and instanciate them
* automatically, use it as given in the example below.
*
* <code>
* <?php
* $gui = new PHPUnit_GUI_SetupDecorator(new PHPUnit_GUI_HTML());
* $gui->getSuitesFromDir('/path/to/dir/tests','.*\.php$',array('index.php','sql.php'));
* $gui->show();
* ?>
* </code>
*
* The example calls this class and tells it to:
*
* - find all file under the directory /path/to/dir/tests
* - for files, which end with '.php' (this is a piece of a regexp, that's why the . is escaped)
* - and to exclude the files 'index.php' and 'sql.php'
* - and include all the files that are left in the tests.
*
* Given that the path (the first parameter) ends with 'tests' it will be assumed
* that the classes are named tests_* where * is the directory plus the filename,
* according to PEAR standards.
*
* So that:
*
* - 'testMe.php' in the dir 'tests' bill be assumed to contain a class tests_testMe
* - '/moretests/aTest.php' should contain a class 'tests_moretests_aTest'
*
* @category Testing
* @package PHPUnit
* @author Wolfram Kriesing <wolfram@kriesing.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PHPUnit
* @since Class available since Release 1.0.0
*/
class PHPUnit_GUI_SetupDecorator
{
/**
*
*
*/
function PHPUnit_GUI_SetupDecorator(&$gui)
{
$this->_gui = &$gui;
}
/**
* just forwarding the action to the decorated class.
*
*/
function show($showPassed=TRUE)
{
$this->_gui->show($showPassed);
}
/**
* Setup test suites that can be found in the given directory
* Using the second parameter you can also choose a subsets of the files found
* in the given directory. I.e. only all the files that contain '_UnitTest_',
* in order to do this simply call it like this:
* <code>getSuitesFromDir($dir,'.*_UnitTest_.*')</code>.
* There you can already see that the pattern is built for the use within a regular expression.
*
* @param string the directory where to search for test-suite files
* @param string the pattern (a regexp) by which to find the files
* @param array an array of file names that shall be excluded
*/
function getSuitesFromDir($dir, $filenamePattern = '', $exclude = array())
{
if ($dir{strlen($dir)-1} == DIRECTORY_SEPARATOR) {
$dir = substr($dir, 0, -1);
}
$files = $this->_getFiles(realpath($dir), $filenamePattern, $exclude, realpath($dir . '/..'));
asort($files);
foreach ($files as $className => $aFile) {
include_once($aFile);
if (class_exists($className)) {
$suites[] =& new PHPUnit_TestSuite($className);
} else {
trigger_error("$className could not be found in $dir$aFile!");
}
}
$this->_gui->addSuites($suites);
}
/**
* This method searches recursively through the directories
* to find all the files that shall be added to the be visible.
*
* @param string the path where find the files
* @param srting the string pattern by which to find the files
* @param string the file names to be excluded
* @param string the root directory, which serves as the prefix to the fully qualified filename
* @access private
*/
function _getFiles($dir, $filenamePattern, $exclude, $rootDir)
{
$files = array();
if ($dp = opendir($dir)) {
while (FALSE !== ($file = readdir($dp))) {
$filename = $dir . DIRECTORY_SEPARATOR . $file;
$match = TRUE;
if ($filenamePattern && !preg_match("~$filenamePattern~", $file)) {
$match = FALSE;
}
if (sizeof($exclude)) {
foreach ($exclude as $aExclude) {
if (strpos($file, $aExclude) !== FALSE) {
$match = FALSE;
break;
}
}
}
if (is_file($filename) && $match) {
$tmp = str_replace($rootDir, '', $filename);
if (strpos($tmp, DIRECTORY_SEPARATOR) === 0) {
$tmp = substr($tmp, 1);
}
if (strpos($tmp, '/') === 0) {
$tmp = substr($tmp, 1);
}
$className = str_replace(DIRECTORY_SEPARATOR, '_', $tmp);
$className = basename($className, '.php');
$files[$className] = $filename;
}
if ($file != '.' && $file != '..' && is_dir($filename)) {
$files = array_merge($files, $this->_getFiles($filename, $filenamePattern, $exclude, $rootDir));
}
}
closedir($dp);
}
return $files;
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>

View File

@ -0,0 +1,154 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* PHP Version 4
*
* Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: RepeatedTest.php,v 1.13 2005/11/10 09:47:14 sebastian Exp $
* @link http://pear.php.net/package/PHPUnit
* @since File available since Release 1.0.0
*/
require_once 'PHPUnit/TestDecorator.php';
/**
* A Decorator that runs a test repeatedly.
*
* Here is an example:
*
* <code>
* <?php
* require_once 'PHPUnit.php';
* require_once 'PHPUnit/RepeatedTest.php';
*
* class MathTest extends PHPUnit_TestCase {
* var $fValue1;
* var $fValue2;
*
* function MathTest($name) {
* $this->PHPUnit_TestCase($name);
* }
*
* function setUp() {
* $this->fValue1 = 2;
* $this->fValue2 = 3;
* }
*
* function testAdd() {
* $this->assertTrue($this->fValue1 + $this->fValue2 == 5);
* }
* }
*
* $suite = new PHPUnit_TestSuite;
*
* $suite->addTest(
* new PHPUnit_RepeatedTest(
* new MathTest('testAdd'),
* 10
* )
* );
*
* $result = PHPUnit::run($suite);
* print $result->toString();
* ?>
* </code>
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PHPUnit
* @since Class available since Release 1.0.0
*/
class PHPUnit_RepeatedTest extends PHPUnit_TestDecorator {
/**
* @var integer
* @access private
*/
var $_timesRepeat = 1;
/**
* Constructor.
*
* @param object
* @param integer
* @access public
*/
function PHPUnit_RepeatedTest(&$test, $timesRepeat = 1) {
$this->PHPUnit_TestDecorator($test);
$this->_timesRepeat = $timesRepeat;
}
/**
* Counts the number of test cases that
* will be run by this test.
*
* @return integer
* @access public
*/
function countTestCases() {
return $this->_timesRepeat * $this->_test->countTestCases();
}
/**
* Runs the decorated test and collects the
* result in a TestResult.
*
* @param object
* @access public
* @abstract
*/
function run(&$result) {
for ($i = 0; $i < $this->_timesRepeat; $i++) {
$this->_test->run($result);
}
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>

View File

@ -0,0 +1,448 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* PHP Version 4
*
* Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package PHPUnit
* @author Scott Mattocks <scott@crisscott.com>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: Skeleton.php,v 1.8 2005/11/10 09:47:14 sebastian Exp $
* @link http://pear.php.net/package/PHPUnit
* @since File available since Release 1.1.0
*/
/**
* Class for creating a PHPUnit_TestCase skeleton file.
*
* This class will take a classname as a parameter on construction and will
* create a PHP file that contains the skeleton of a PHPUnit_TestCase
* subclass. The test case will contain a test foreach method of the class.
* Methods of the parent class will, by default, be excluded from the test
* class. Passing and optional construction parameter will include them.
*
* Example
*
* <?php
* require_once 'PHPUnit/Skeleton.php';
* $ps = new PHPUnit_Skeleton('PHPUnit_Skeleton', 'PHPUnit/Skeleton.php');
*
* // Generate the test class.
* // Default settings will not include any parent class methods, but
* // will include private methods.
* $ps->createTestClass();
*
* // Write the new test class to file.
* // By default, code to run the test will be included.
* $ps->writeTestClass();
* ?>
*
* Now open the skeleton class and fill in the details.
* If you run the test as is, all tests will fail and
* you will see plenty of undefined constant errors.
*
* @category Testing
* @package PHPUnit
* @author Scott Mattocks <scott@crisscott.com>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PHPUnit
* @since Class available since Release 1.1.0
*/
class PHPUnit_Skeleton {
/**
* Path to the class file to create a skeleton for.
* @var string
*/
var $classPath;
/**
* The name of the class
* @var string
*/
var $className;
/**
* Path to the configuration file needed by class to test.
* @var string
*/
var $configFile;
/**
* Whether or not to include the methods of the parent class when testing.
* @var boolean
*/
var $includeParents;
/**
* Whether or not to test private methods.
* @var boolean
*/
var $includePrivate;
/**
* The test class that will be created.
* @var string
*/
var $testClass;
/**
* Constructor. Sets the class members and check that the class
* to test is accessible.
*
* @access public
* @param string $className
* @param string $classPath
* @param boolean $includeParents Wheter to include the parent's methods in the test.
* @return void
*/
function PHPUnit_Skeleton($className, $classPath, $includeParents = FALSE, $includePrivate = TRUE) {
// Set up the members.
if (@is_readable($classPath)) {
$this->className = $className;
$this->classPath = $classPath;
} else {
$this->_handleErrors($classPath . ' is not readable. Cannot create test class.');
}
// Do we want to include parent methods?
$this->includeParents = $includeParents;
// Do we want to allow private methods?
$this->includePrivate = $includePrivate;
}
/**
* The class to test may require a special config file before it can be
* instantiated. This method lets you set that file.
*
* @access public
* @param string $configPath
* @return void
*/
function setConfigFile($configFile) {
// Check that the file is readable
if (@is_readable($configFile)) {
$this->configFile = $configFile;
} else {
$this->_handleErrors($configFile . ' is not readable. Cannot create test class.');
}
}
/**
* Create the code that will be the skeleton of the test case.
*
* The test case must have a clss definition, one var, a constructor
* setUp, tearDown, and methods. Optionally and by default the code
* to run the test is added when the class is written to file.
*
* @access public
* @param none
* @return void
*/
function createTestClass() {
// Instantiate the object.
if (isset($this->configFile)) {
require_once $this->configFile;
}
require_once $this->classPath;
// Get the methods.
$classMethods = get_class_methods($this->className);
// Remove the parent methods if needed.
if (!$this->includeParents) {
$parentMethods = get_class_methods(get_parent_class($this->className));
if (count($parentMethods)) {
$classMethods = array_diff($classMethods, $parentMethods);
}
}
// Create the class definition, constructor, setUp and tearDown.
$this->_createDefinition();
$this->_createConstructor();
$this->_createSetUpTearDown();
if (count($classMethods)) {
// Foreach method create a test case.
foreach ($classMethods as $method) {
// Unless it is the constructor.
if (strcasecmp($this->className, $method) !== 0) {
// Check for private methods.
if (!$this->includePrivate && strpos($method, '_') === 0) {
continue;
} else {
$this->_createMethod($method);
}
}
}
}
// Finis off the class.
$this->_finishClass();
}
/**
* Create the class definition.
*
* The definition consist of a header comment, require statment
* for getting the PHPUnit file, the actual class definition,
* and the definition of the class member variable.
*
* All of the code needed for the new class is stored in the
* testClass member.
*
* @access private
* @param none
* @return void
*/
function _createDefinition() {
// Create header comment.
$this->testClass =
"/**\n" .
" * PHPUnit test case for " . $this->className . "\n" .
" * \n" .
" * The method skeletons below need to be filled in with \n" .
" * real data so that the tests will run correctly. Replace \n" .
" * all EXPECTED_VAL and PARAM strings with real data. \n" .
" * \n" .
" * Created with PHPUnit_Skeleton on " . date('Y-m-d') . "\n" .
" */\n";
// Add the require statements.
$this->testClass .= "require_once 'PHPUnit.php';\n";
// Add the class definition and variable definition.
$this->testClass .=
"class " . $this->className . "Test extends PHPUnit_TestCase {\n\n" .
" var \$" . $this->className . ";\n\n";
}
/**
* Create the class constructor. (PHP4 style)
*
* The constructor simply calls the PHPUnit_TestCase method.
* This code is taken from the PHPUnit documentation.
*
* All of the code needed for the new class is stored in the
* testClass member.
*
* @access private
* @param none
* @return void
*/
function _createConstructor() {
// Create the test class constructor.
$this->testClass.=
" function " . $this->className . "Test(\$name)\n" .
" {\n" .
" \$this->PHPUnit_TestCase(\$name);\n" .
" }\n\n";
}
/**
* Create setUp and tearDown methods.
*
* The setUp method creates the instance of the object to test.
* The tearDown method releases the instance.
* This code is taken from the PHPUnit documentation.
*
* All of the code needed for the new class is stored in the
* testClass member.
*
* @access private
* @param none
* @return void
*/
function _createSetUpTearDown() {
// Create the setUp method.
$this->testClass .=
" function setUp()\n" .
" {\n";
if (isset($this->configFile)) {
$this->testClass .=
" require_once '" . $this->configFile . "';\n";
}
$this->testClass .=
" require_once '" . $this->classPath . "';\n" .
" \$this->" . $this->className . " =& new " . $this->className . "(PARAM);\n" .
" }\n\n";
// Create the tearDown method.
$this->testClass .=
" function tearDown()\n" .
" {\n" .
" unset(\$this->" . $this->className . ");\n" .
" }\n\n";
}
/**
* Create a basic skeleton for test methods.
*
* This code is taken from the PHPUnit documentation.
*
* All of the code needed for the new class is stored in the
* testClass member.
*
* @access private
* @param none
* @return void
*/
function _createMethod($methodName) {
// Create a test method.
$this->testClass .=
" function test" . $methodName . "()\n" .
" {\n" .
" \$result = \$this->" . $this->className . "->" . $methodName . "(PARAM);\n" .
" \$expected = EXPECTED_VAL;\n" .
" \$this->assertEquals(\$expected, \$result);\n" .
" }\n\n";
}
/**
* Add the closing brace needed for a proper class definition.
*
* All of the code needed for the new class is stored in the
* testClass member.
*
* @access private
* @param none
* @return void
*/
function _finishClass() {
// Close off the class.
$this->testClass.= "}\n";
}
/**
* Create the code that will actually run the test.
*
* This code is added by default so that the test can be run
* just by running the file. To have it not added pass false
* as the second parameter to the writeTestClass method.
* This code is taken from the PHPUnit documentation.
*
* All of the code needed for the new class is stored in the
* testClass member.
*
* @access private
* @param none
* @return void
*/
function _createTest() {
// Create a call to the test.
$test =
"// Running the test.\n" .
"\$suite = new PHPUnit_TestSuite('" . $this->className . "Test');\n" .
"\$result = PHPUnit::run(\$suite);\n" .
"echo \$result->toString();\n";
return $test;
}
/**
* Write the test class to file.
*
* This will write the test class created using the createTestClass
* method to a file called <className>Test.php. By default the file
* is written to the current directory and will have code to run
* the test appended to the bottom of the file.
*
* @access public
* @param string $destination The directory to write the file to.
* @param boolean $addTest Wheter to add the test running code.
* @return void
*/
function writeTestClass($destination = './', $addTest = TRUE) {
// Check for something to write to file.
if (!isset($this->testClass)) {
$this->_handleErrors('Noting to write.', PHPUS_WARNING);
return;
}
// Open the destination file.
$fp = fopen($destination . $this->className . 'Test.php', 'w');
fwrite($fp, "<?php\n");
// Write the test class.
fwrite($fp, $this->testClass);
// Add the call to test the class in the file if we were asked to.
if ($addTest) {
fwrite($fp, $this->_createTest());
}
// Close the file.
fwrite($fp, "?>\n");
fclose($fp);
}
/**
* Error handler.
*
* This method should be rewritten to use the prefered error
* handling method. (PEAR_ErrorStack)
*
* @access private
* @param string $message The error message.
* @param integer $type An indication of the severity of the error.
* @return void Code may cause PHP to exit.
*/
function _handleErrors($message, $type = E_USER_ERROR) {
// For now just echo the message.
echo $message;
// Check to see if we should quit.
if ($type == E_USER_ERROR) {
exit;
}
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>

View File

@ -0,0 +1,293 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* PHP Version 4
*
* Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: TestCase.php,v 1.21 2005/11/10 09:47:14 sebastian Exp $
* @link http://pear.php.net/package/PHPUnit
* @since File available since Release 1.0.0
*/
require_once 'PHPUnit/Assert.php';
require_once 'PHPUnit/TestResult.php';
/**
* A TestCase defines the fixture to run multiple tests.
*
* To define a TestCase
*
* 1) Implement a subclass of PHPUnit_TestCase.
* 2) Define instance variables that store the state of the fixture.
* 3) Initialize the fixture state by overriding setUp().
* 4) Clean-up after a test by overriding tearDown().
*
* Each test runs in its own fixture so there can be no side effects
* among test runs.
*
* Here is an example:
*
* <code>
* <?php
* class MathTest extends PHPUnit_TestCase {
* var $fValue1;
* var $fValue2;
*
* function MathTest($name) {
* $this->PHPUnit_TestCase($name);
* }
*
* function setUp() {
* $this->fValue1 = 2;
* $this->fValue2 = 3;
* }
* }
* ?>
* </code>
*
* For each test implement a method which interacts with the fixture.
* Verify the expected results with assertions specified by calling
* assert with a boolean.
*
* <code>
* <?php
* function testPass() {
* $this->assertTrue($this->fValue1 + $this->fValue2 == 5);
* }
* ?>
* </code>
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PHPUnit
* @since Class available since Release 1.0.0
*/
class PHPUnit_TestCase extends PHPUnit_Assert {
/**
* @var boolean
* @access private
*/
var $_failed = FALSE;
/**
* The name of the test case.
*
* @var string
* @access private
*/
var $_name = '';
/**
* PHPUnit_TestResult object
*
* @var object
* @access private
*/
var $_result;
/**
* Constructs a test case with the given name.
*
* @param string
* @access public
*/
function PHPUnit_TestCase($name = FALSE) {
if ($name !== FALSE) {
$this->setName($name);
}
}
/**
* Counts the number of test cases executed by run(TestResult result).
*
* @return integer
* @access public
*/
function countTestCases() {
return 1;
}
/**
* Gets the name of a TestCase.
*
* @return string
* @access public
*/
function getName() {
return $this->_name;
}
/**
* Runs the test case and collects the results in a given TestResult object.
*
* @param object
* @return object
* @access public
*/
function run(&$result) {
$this->_result = &$result;
$this->_result->run($this);
return $this->_result;
}
/**
* Runs the bare test sequence.
*
* @access public
*/
function runBare() {
$this->setUp();
$this->runTest();
$this->tearDown();
$this->pass();
}
/**
* Override to run the test and assert its state.
*
* @access protected
*/
function runTest() {
call_user_func(
array(
&$this,
$this->_name
)
);
}
/**
* Sets the name of a TestCase.
*
* @param string
* @access public
*/
function setName($name) {
$this->_name = $name;
}
/**
* Returns a string representation of the test case.
*
* @return string
* @access public
*/
function toString() {
return '';
}
/**
* Creates a default TestResult object.
*
* @return object
* @access protected
*/
function &createResult() {
return new PHPUnit_TestResult;
}
/**
* Fails a test with the given message.
*
* @param string
* @access protected
*/
function fail($message = '') {
if (function_exists('debug_backtrace')) {
$trace = debug_backtrace();
if (isset($trace['1']['file'])) {
$message = sprintf(
"%s in %s:%s",
$message,
$trace['1']['file'],
$trace['1']['line']
);
}
}
$this->_result->addFailure($this, $message);
$this->_failed = TRUE;
}
/**
* Passes a test.
*
* @access protected
*/
function pass() {
if (!$this->_failed) {
$this->_result->addPassedTest($this);
}
}
/**
* Sets up the fixture, for example, open a network connection.
* This method is called before a test is executed.
*
* @access protected
* @abstract
*/
function setUp() { /* abstract */ }
/**
* Tears down the fixture, for example, close a network connection.
* This method is called after a test is executed.
*
* @access protected
* @abstract
*/
function tearDown() { /* abstract */ }
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>

View File

@ -0,0 +1,156 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* PHP Version 4
*
* Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: TestDecorator.php,v 1.17 2005/11/10 09:47:14 sebastian Exp $
* @link http://pear.php.net/package/PHPUnit
* @since File available since Release 1.0.0
*/
require_once 'PHPUnit/TestCase.php';
require_once 'PHPUnit/TestSuite.php';
if (!function_exists('is_a')) {
require_once 'PHP/Compat/Function/is_a.php';
}
/**
* A Decorator for Tests.
*
* Use TestDecorator as the base class for defining new
* test decorators. Test decorator subclasses can be introduced
* to add behaviour before or after a test is run.
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PHPUnit
* @since Class available since Release 1.0.0
*/
class PHPUnit_TestDecorator {
/**
* The Test to be decorated.
*
* @var object
* @access protected
*/
var $_test = NULL;
/**
* Constructor.
*
* @param object
* @access public
*/
function PHPUnit_TestDecorator(&$test) {
if (is_object($test) &&
(is_a($test, 'PHPUnit_TestCase') ||
is_a($test, 'PHPUnit_TestSuite'))) {
$this->_test = &$test;
}
}
/**
* Runs the test and collects the
* result in a TestResult.
*
* @param object
* @access public
*/
function basicRun(&$result) {
$this->_test->run($result);
}
/**
* Counts the number of test cases that
* will be run by this test.
*
* @return integer
* @access public
*/
function countTestCases() {
return $this->_test->countTestCases();
}
/**
* Returns the test to be run.
*
* @return object
* @access public
*/
function &getTest() {
return $this->_test;
}
/**
* Runs the decorated test and collects the
* result in a TestResult.
*
* @param object
* @access public
* @abstract
*/
function run(&$result) { /* abstract */ }
/**
* Returns a string representation of the test.
*
* @return string
* @access public
*/
function toString() {
return $this->_test->toString();
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>

View File

@ -0,0 +1,130 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* PHP Version 4
*
* Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: TestFailure.php,v 1.13 2005/11/10 09:47:14 sebastian Exp $
* @link http://pear.php.net/package/PHPUnit
* @since File available since Release 1.0.0
*/
/**
* A TestFailure collects a failed test together with the caught exception.
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PHPUnit
* @since Class available since Release 1.0.0
*/
class PHPUnit_TestFailure {
/**
* @var object
* @access private
*/
var $_failedTest;
/**
* @var string
* @access private
*/
var $_thrownException;
/**
* Constructs a TestFailure with the given test and exception.
*
* @param object
* @param string
* @access public
*/
function PHPUnit_TestFailure(&$failedTest, &$thrownException) {
$this->_failedTest = &$failedTest;
$this->_thrownException = &$thrownException;
}
/**
* Gets the failed test.
*
* @return object
* @access public
*/
function &failedTest() {
return $this->_failedTest;
}
/**
* Gets the thrown exception.
*
* @return object
* @access public
*/
function &thrownException() {
return $this->_thrownException;
}
/**
* Returns a short description of the failure.
*
* @return string
* @access public
*/
function toString() {
return sprintf(
"TestCase %s->%s() failed: %s\n",
get_class($this->_failedTest),
$this->_failedTest->getName(),
$this->_thrownException
);
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>

View File

@ -0,0 +1,162 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* PHP Version 4
*
* Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: TestListener.php,v 1.12 2005/11/10 09:47:15 sebastian Exp $
* @link http://pear.php.net/package/PHPUnit
* @since File available since Release 1.0.0
*/
/**
* A Listener for test progress.
*
* Here is an example:
*
* <code>
* <?php
* require_once 'PHPUnit.php';
* require_once 'PHPUnit/TestListener.php';
*
* class MathTest extends PHPUnit_TestCase {
* var $fValue1;
* var $fValue2;
*
* function MathTest($name) {
* $this->PHPUnit_TestCase($name);
* }
*
* function setUp() {
* $this->fValue1 = 2;
* $this->fValue2 = 3;
* }
*
* function testAdd() {
* $this->assertTrue($this->fValue1 + $this->fValue2 == 4);
* }
* }
*
* class MyListener extends PHPUnit_TestListener {
* function addError(&$test, &$t) {
* print "MyListener::addError() called.\n";
* }
*
* function addFailure(&$test, &$t) {
* print "MyListener::addFailure() called.\n";
* }
*
* function endTest(&$test) {
* print "MyListener::endTest() called.\n";
* }
*
* function startTest(&$test) {
* print "MyListener::startTest() called.\n";
* }
* }
*
* $suite = new PHPUnit_TestSuite;
* $suite->addTest(new MathTest('testAdd'));
*
* $result = new PHPUnit_TestResult;
* $result->addListener(new MyListener);
*
* $suite->run($result);
* print $result->toString();
* ?>
* </code>
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PHPUnit
* @since Class available since Release 1.0.0
*/
class PHPUnit_TestListener {
/**
* An error occurred.
*
* @param object
* @param object
* @access public
* @abstract
*/
function addError(&$test, &$t) { /*abstract */ }
/**
* A failure occurred.
*
* @param object
* @param object
* @access public
* @abstract
*/
function addFailure(&$test, &$t) { /*abstract */ }
/**
* A test ended.
*
* @param object
* @access public
* @abstract
*/
function endTest(&$test) { /*abstract */ }
/**
* A test started.
*
* @param object
* @access public
* @abstract
*/
function startTest(&$test) { /*abstract */ }
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>

View File

@ -0,0 +1,347 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* PHP Version 4
*
* Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: TestResult.php,v 1.18 2005/11/10 09:47:15 sebastian Exp $
* @link http://pear.php.net/package/PHPUnit
* @since File available since Release 1.0.0
*/
require_once 'PHPUnit/TestFailure.php';
require_once 'PHPUnit/TestListener.php';
if (!function_exists('is_a')) {
require_once 'PHP/Compat/Function/is_a.php';
}
/**
* A TestResult collects the results of executing a test case.
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PHPUnit
* @since Class available since Release 1.0.0
*/
class PHPUnit_TestResult {
/**
* @var array
* @access protected
*/
var $_errors = array();
/**
* @var array
* @access protected
*/
var $_failures = array();
/**
* @var array
* @access protected
*/
var $_listeners = array();
/**
* @var array
* @access protected
*/
var $_passedTests = array();
/**
* @var integer
* @access protected
*/
var $_runTests = 0;
/**
* @var boolean
* @access private
*/
var $_stop = FALSE;
/**
* Adds an error to the list of errors.
* The passed in exception caused the error.
*
* @param object
* @param object
* @access public
*/
function addError(&$test, &$t) {
$this->_errors[] = new PHPUnit_TestFailure($test, $t);
for ($i = 0; $i < sizeof($this->_listeners); $i++) {
$this->_listeners[$i]->addError($test, $t);
}
}
/**
* Adds a failure to the list of failures.
* The passed in exception caused the failure.
*
* @param object
* @param object
* @access public
*/
function addFailure(&$test, &$t) {
$this->_failures[] = new PHPUnit_TestFailure($test, $t);
for ($i = 0; $i < sizeof($this->_listeners); $i++) {
$this->_listeners[$i]->addFailure($test, $t);
}
}
/**
* Registers a TestListener.
*
* @param object
* @access public
*/
function addListener(&$listener) {
if (is_object($listener) &&
is_a($listener, 'PHPUnit_TestListener')) {
$this->_listeners[] = &$listener;
}
}
/**
* Adds a passed test to the list of passed tests.
*
* @param object
* @access public
*/
function addPassedTest(&$test) {
$this->_passedTests[] = &$test;
}
/**
* Informs the result that a test was completed.
*
* @param object
* @access public
*/
function endTest(&$test) {
for ($i = 0; $i < sizeof($this->_listeners); $i++) {
$this->_listeners[$i]->endTest($test);
}
}
/**
* Gets the number of detected errors.
*
* @return integer
* @access public
*/
function errorCount() {
return sizeof($this->_errors);
}
/**
* Returns an Enumeration for the errors.
*
* @return array
* @access public
*/
function &errors() {
return $this->_errors;
}
/**
* Gets the number of detected failures.
*
* @return integer
* @access public
*/
function failureCount() {
return sizeof($this->_failures);
}
/**
* Returns an Enumeration for the failures.
*
* @return array
* @access public
*/
function &failures() {
return $this->_failures;
}
/**
* Returns an Enumeration for the passed tests.
*
* @return array
* @access public
*/
function &passedTests() {
return $this->_passedTests;
}
/**
* Unregisters a TestListener.
* This requires the Zend Engine 2 (to work properly).
*
* @param object
* @access public
*/
function removeListener(&$listener) {
for ($i = 0; $i < sizeof($this->_listeners); $i++) {
if ($this->_listeners[$i] === $listener) {
unset($this->_listeners[$i]);
}
}
}
/**
* Runs a TestCase.
*
* @param object
* @access public
*/
function run(&$test) {
$this->startTest($test);
$this->_runTests++;
$test->runBare();
$this->endTest($test);
}
/**
* Gets the number of run tests.
*
* @return integer
* @access public
*/
function runCount() {
return $this->_runTests;
}
/**
* Checks whether the test run should stop.
*
* @access public
*/
function shouldStop() {
return $this->_stop;
}
/**
* Informs the result that a test will be started.
*
* @param object
* @access public
*/
function startTest(&$test) {
for ($i = 0; $i < sizeof($this->_listeners); $i++) {
$this->_listeners[$i]->startTest($test);
}
}
/**
* Marks that the test run should stop.
*
* @access public
*/
function stop() {
$this->_stop = TRUE;
}
/**
* Returns a HTML representation of the test result.
*
* @return string
* @access public
*/
function toHTML() {
return '<pre>' . htmlspecialchars($this->toString()) . '</pre>';
}
/**
* Returns a text representation of the test result.
*
* @return string
* @access public
*/
function toString() {
$result = '';
foreach ($this->_passedTests as $passedTest) {
$result .= sprintf(
"TestCase %s->%s() passed\n",
get_class($passedTest),
$passedTest->getName()
);
}
foreach ($this->_failures as $failedTest) {
$result .= $failedTest->toString();
}
return $result;
}
/**
* Returns whether the entire test was successful or not.
*
* @return boolean
* @access public
*/
function wasSuccessful() {
if (empty($this->_errors) && empty($this->_failures)) {
return TRUE;
} else {
return FALSE;
}
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>

View File

@ -0,0 +1,262 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* PHP Version 4
*
* Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* * Neither the name of Sebastian Bergmann nor the names of his
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: TestSuite.php,v 1.17 2005/11/10 09:47:15 sebastian Exp $
* @link http://pear.php.net/package/PHPUnit
* @since File available since Release 1.0.0
*/
require_once 'PHPUnit/TestCase.php';
/**
* A TestSuite is a Composite of Tests. It runs a collection of test cases.
*
* Here is an example using the dynamic test definition.
*
* <code>
* <?php
* $suite = new PHPUnit_TestSuite();
* $suite->addTest(new MathTest('testPass'));
* ?>
* </code>
*
* Alternatively, a TestSuite can extract the tests to be run automatically.
* To do so you pass the classname of your TestCase class to the TestSuite
* constructor.
*
* <code>
* <?php
* $suite = new TestSuite('classname');
* ?>
* </code>
*
* This constructor creates a suite with all the methods starting with
* "test" that take no arguments.
*
* @category Testing
* @package PHPUnit
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
* @copyright 2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/PHPUnit
* @since Class available since Release 1.0.0
*/
class PHPUnit_TestSuite {
/**
* The name of the test suite.
*
* @var string
* @access private
*/
var $_name = '';
/**
* The tests in the test suite.
*
* @var array
* @access private
*/
var $_tests = array();
/**
* Constructs a TestSuite.
*
* @param mixed
* @access public
*/
function PHPUnit_TestSuite($test = FALSE) {
if ($test !== FALSE) {
$this->setName($test);
$this->addTestSuite($test);
}
}
/**
* Adds a test to the suite.
*
* @param object
* @access public
*/
function addTest(&$test) {
$this->_tests[] = &$test;
}
/**
* Adds the tests from the given class to the suite.
*
* @param string
* @access public
*/
function addTestSuite($testClass) {
if (class_exists($testClass)) {
$methods = get_class_methods($testClass);
$parentClasses = array(strtolower($testClass));
$parentClass = $testClass;
while(is_string($parentClass = get_parent_class($parentClass))) {
$parentClasses[] = $parentClass;
}
foreach ($methods as $method) {
if (substr($method, 0, 4) == 'test' &&
!in_array($method, $parentClasses)) {
$this->addTest(new $testClass($method));
}
}
}
}
/**
* Counts the number of test cases that will be run by this test.
*
* @return integer
* @access public
*/
function countTestCases() {
$count = 0;
foreach ($this->_tests as $test) {
$count += $test->countTestCases();
}
return $count;
}
/**
* Returns the name of the suite.
*
* @return string
* @access public
*/
function getName() {
return $this->_name;
}
/**
* Runs the tests and collects their result in a TestResult.
*
* @param object
* @access public
*/
function run(&$result) {
for ($i = 0; $i < sizeof($this->_tests) && !$result->shouldStop(); $i++) {
$this->_tests[$i]->run($result);
}
}
/**
* Runs a test.
*
* @param object
* @param object
* @access public
*/
function runTest(&$test, &$result) {
$test->run($result);
}
/**
* Sets the name of the suite.
*
* @param string
* @access public
*/
function setName($name) {
$this->_name = $name;
}
/**
* Returns the test at the given index.
*
* @param integer
* @return object
* @access public
*/
function &testAt($index) {
if (isset($this->_tests[$index])) {
return $this->_tests[$index];
} else {
return FALSE;
}
}
/**
* Returns the number of tests in this suite.
*
* @return integer
* @access public
*/
function testCount() {
return sizeof($this->_tests);
}
/**
* Returns the tests as an enumeration.
*
* @return array
* @access public
*/
function &tests() {
return $this->_tests;
}
/**
* Returns a string representation of the test suite.
*
* @return string
* @access public
*/
function toString() {
return '';
}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* c-hanging-comment-ender-p: nil
* End:
*/
?>

View File

@ -1,4 +1,5 @@
Last updated: Last updated:
- 2010-09-13: PHPUnit added
- 2010-08-17: Updated everything to latest version - 2010-08-17: Updated everything to latest version
- 2007-02-13: Update DB from 1.7.6 to 1.7.9 - 2007-02-13: Update DB from 1.7.6 to 1.7.9
@ -16,3 +17,4 @@ Last updated:
* XML_RPC-1.5.4 * XML_RPC-1.5.4
* XML_Serializer-0.20.0(beta) * XML_Serializer-0.20.0(beta)
* XML_Util-1.2.1 * XML_Util-1.2.1
* PHPUnit 1.3.2