BUGFIX: Fixing tests

git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@66508 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
Sam Minnee 2008-11-24 19:28:46 +00:00
parent 96c5be8252
commit 2e955b498e
14 changed files with 119 additions and 116 deletions

View File

@ -96,9 +96,7 @@ class ComponentSet extends DataObjectSet {
$item = DataObject::get_by_id($this->childClass, $item); $item = DataObject::get_by_id($this->childClass, $item);
if(!isset($item)) { if(!$item) return;
return;
}
} }
// If we've already got a database object, then update the database // If we've already got a database object, then update the database

View File

@ -122,11 +122,6 @@ abstract class Database extends Object {
*/ */
abstract function enumValuesForField($tableName, $fieldName); abstract function enumValuesForField($tableName, $fieldName);
/**
* Convert a SQLQuery object into a SQL statement
*/
abstract function sqlQueryToString(SQLQuery $sqlQuery);
/** /**
* The table list, generated by the tableList() function. * The table list, generated by the tableList() function.
* Used by the requireTable() function. * Used by the requireTable() function.
@ -420,12 +415,15 @@ abstract class Database extends Object {
switch($writeInfo['command']) { switch($writeInfo['command']) {
case "update": case "update":
$fieldList = implode(", ", $fieldList); // Test to see if this update query shouldn't, in fact, be an insert
$sql = "update \"$table\" SET $fieldList where $writeInfo[where]"; if($this->query("SELECT \"ID\" FROM \"$table\" WHERE $writeInfo[where]")->value()) {
$this->query($sql); $fieldList = implode(", ", $fieldList);
$sql = "update \"$table\" SET $fieldList where $writeInfo[where]";
$this->query($sql);
break;
}
// If affectedRows = 0, then don't break, meaning the insert query below gets called // ...if not, we'll skip on to the insert code
if($this->affectedRows()) break;
case "insert": case "insert":
if(!isset($writeInfo['fields']['ID']) && isset($writeInfo['id'])) { if(!isset($writeInfo['fields']['ID']) && isset($writeInfo['id'])) {
@ -483,32 +481,73 @@ abstract class Database extends Object {
} }
static function alteration_message($message,$type=""){ static function alteration_message($message,$type=""){
if(!Database::$supressOutput) { if(!Database::$supressOutput) {
$color = ""; $color = "";
switch ($type){ switch ($type){
case "created": case "created":
$color = "green"; $color = "green";
break; break;
case "obsolete": case "obsolete":
$color = "red"; $color = "red";
break; break;
case "error": case "error":
$color = "red"; $color = "red";
break; break;
case "deleted": case "deleted":
$color = "red"; $color = "red";
break; break;
case "changed": case "changed":
$color = "blue"; $color = "blue";
break; break;
case "repaired": case "repaired":
$color = "blue"; $color = "blue";
break; break;
default: default:
$color=""; $color="";
}
echo "<li style=\"color: $color\">$message</li>";
} }
echo "<li style=\"color: $color\">$message</li>";
}
}
/**
* Convert a SQLQuery object into a SQL statement
*/
public function sqlQueryToString(SQLQuery $sqlQuery) {
if (!$sqlQuery->from) return '';
$distinct = $sqlQuery->distinct ? "DISTINCT " : "";
if($sqlQuery->delete) {
$text = "DELETE ";
} else if($sqlQuery->select) {
$text = "SELECT $distinct" . implode(", ", $sqlQuery->select);
}
$text .= " FROM " . implode(" ", $sqlQuery->from);
if($sqlQuery->where) $text .= " WHERE (" . $sqlQuery->getFilter(). ")";
if($sqlQuery->groupby) $text .= " GROUP BY " . implode(", ", $sqlQuery->groupby);
if($sqlQuery->having) $text .= " HAVING ( " . implode(" ) AND ( ", $sqlQuery->having) . " )";
if($sqlQuery->orderby) $text .= " ORDER BY " . $sqlQuery->orderby;
if($sqlQuery->limit) {
$limit = $sqlQuery->limit;
// Pass limit as array or SQL string value
if(is_array($limit)) {
if(!array_key_exists('limit',$limit)) user_error('SQLQuery::limit(): Wrong format for $limit', E_USER_ERROR);
if(isset($limit['start']) && is_numeric($limit['start']) && isset($limit['limit']) && is_numeric($limit['limit'])) {
$combinedLimit = "$limit[limit] OFFSET $limit[start]";
} elseif(isset($limit['limit']) && is_numeric($limit['limit'])) {
$combinedLimit = (int)$limit['limit'];
} else {
$combinedLimit = false;
}
if(!empty($combinedLimit)) $text .= " LIMIT " . $combinedLimit;
} else {
$text .= " LIMIT " . $sqlQuery->limit;
}
}
return $text;
} }
} }

View File

@ -552,7 +552,7 @@ class Hierarchy extends DataObjectDecorator {
if(!$afterNode || $afterNode->ParentID != $this->owner->ID) { if(!$afterNode || $afterNode->ParentID != $this->owner->ID) {
$children = $this->AllChildren(); $children = $this->AllChildren();
} else { } else {
$children = DataObject::get(ClassInfo::baseDataClass($this->owner->class), "\"$baseClass\".\"ParentID\"={$this->owner->ID}" . ( ( $afterNode ) ? " AND \"Sort\" > " . sprintf( '%d', $afterNode->Sort ) : "" ), '\"Sort\" ASC'); $children = DataObject::get(ClassInfo::baseDataClass($this->owner->class), "\"$baseClass\".\"ParentID\"={$this->owner->ID}" . ( ( $afterNode ) ? " AND \"Sort\" > " . sprintf( '%d', $afterNode->Sort ) : "" ), '"Sort" ASC');
} }
// Try all the siblings of this node after the given node // Try all the siblings of this node after the given node

View File

@ -563,49 +563,6 @@ class MySQLDatabase extends Database {
} }
return $classes; return $classes;
} }
/**
* Convert a SQLQuery object into a SQL statement
*/
public function sqlQueryToString(SQLQuery $sqlQuery) {
if (!$sqlQuery->from) return '';
$distinct = $sqlQuery->distinct ? "DISTINCT " : "";
if($sqlQuery->delete) {
$text = "DELETE ";
} else if($sqlQuery->select) {
$text = "SELECT $distinct" . implode(", ", $sqlQuery->select);
}
$text .= " FROM " . implode(" ", $sqlQuery->from);
if($sqlQuery->where) $text .= " WHERE (" . $sqlQuery->getFilter(). ")";
if($sqlQuery->groupby) $text .= " GROUP BY " . implode(", ", $sqlQuery->groupby);
if($sqlQuery->having) $text .= " HAVING ( " . implode(" ) AND ( ", $sqlQuery->having) . " )";
if($sqlQuery->orderby) $text .= " ORDER BY " . $sqlQuery->orderby;
if($sqlQuery->limit) {
$limit = $sqlQuery->limit;
// Pass limit as array or SQL string value
if(is_array($limit)) {
if(!array_key_exists('limit',$limit)) user_error('SQLQuery::limit(): Wrong format for $limit', E_USER_ERROR);
if(isset($limit['start']) && is_numeric($limit['start']) && isset($limit['limit']) && is_numeric($limit['limit'])) {
// @todo MySQL specific LIMIT syntax
$combinedLimit = "$limit[limit] OFFSET $limit[start]";
} elseif(isset($limit['limit']) && is_numeric($limit['limit'])) {
$combinedLimit = (int)$limit['limit'];
} else {
$combinedLimit = false;
}
if(!empty($combinedLimit)) $this->limit = $combinedLimit;
} else {
$text .= " LIMIT " . $sqlQuery->limit;
}
}
return $text;
}
} }
/** /**

View File

@ -1376,12 +1376,22 @@ class SiteTree extends DataObject {
GoogleSitemap::ping(); GoogleSitemap::ping();
// Fix the sort order for this page's siblings if(DB::getConn() instanceof MySQLDatabase) {
DB::query("UPDATE \"SiteTree_Live\" // Special syntax for MySQL (grr!)
SET \"Sort\" = \"SiteTree\".\"Sort\" // More ANSI-compliant syntax
FROM \"SiteTree\" DB::query("UPDATE \"SiteTree_Live\", \"SiteTree\"
WHERE \"SiteTree_Live\".\"ID\" = \"SiteTree\".\"ID\" SET \"SiteTree_Live\".\"Sort\" = \"SiteTree\".\"Sort\"
AND \"SiteTree_Live\".\"ParentID\" = " . sprintf('%d', $this->ParentID) ); WHERE \"SiteTree_Live\".\"ID\" = \"SiteTree\".\"ID\"
AND \"SiteTree_Live\".\"ParentID\" = " . sprintf('%d', $this->ParentID) );
} else {
// More ANSI-compliant syntax
DB::query("UPDATE \"SiteTree_Live\"
FROM \"SiteTree\"
SET \"Sort\" = \"SiteTree\".\"Sort\"
WHERE \"SiteTree_Live\".\"ID\" = \"SiteTree\".\"ID\"
AND \"SiteTree_Live\".\"ParentID\" = " . sprintf('%d', $this->ParentID) );
}
// Handle activities undertaken by decorators // Handle activities undertaken by decorators
$this->extend('onAfterPublish', $original); $this->extend('onAfterPublish', $original);

View File

@ -381,7 +381,7 @@ class Translatable extends DataObjectDecorator {
* that is not a translatable field) * that is not a translatable field)
*/ */
$clauseparts = explode('.',$innerparts[1]); $clauseparts = explode('.',$innerparts[1]);
$originalTable = str_replace('\"','',str_replace('_lang','',$clauseparts[0])); $originalTable = str_replace('"','',str_replace('_lang','',$clauseparts[0]));
$parts[$j] = ($this->isInAugmentedTable($clauseparts[1], $originalTable) ? "\"{$originalTable}_lang\"" : "\"$originalTable\"") $parts[$j] = ($this->isInAugmentedTable($clauseparts[1], $originalTable) ? "\"{$originalTable}_lang\"" : "\"$originalTable\"")
. ".{$clauseparts[1]}{$innerparts[2]}"; . ".{$clauseparts[1]}{$innerparts[2]}";
} }
@ -407,7 +407,7 @@ class Translatable extends DataObjectDecorator {
/* if we are selecting fields (not doing counts for example) we need to select everything from /* if we are selecting fields (not doing counts for example) we need to select everything from
* the original table (was renamed to _lang) since some fields that we require may be there * the original table (was renamed to _lang) since some fields that we require may be there
*/ */
if ($query->select[0][0] == '\"') $query->select = array_merge(array("\"$table\".*"),$query->select); if ($query->select[0][0] == '"') $query->select = array_merge(array("\"$table\".*"),$query->select);
} else unset($query->from[$table]); } else unset($query->from[$table]);
} else { } else {
$query->from[$table] = str_replace("\"{$table}\".OriginalLangID","\"{$table}\".ID",$query->from[$table]); $query->from[$table] = str_replace("\"{$table}\".OriginalLangID","\"{$table}\".ID",$query->from[$table]);

View File

@ -452,7 +452,7 @@ class Versioned extends DataObjectDecorator {
$query = $this->owner->extendedSQL($filter,""); $query = $this->owner->extendedSQL($filter,"");
foreach($query->from as $table => $join) { foreach($query->from as $table => $join) {
if($join[0] == '\"') $baseTable = str_replace('\"','',$join); if($join[0] == '"') $baseTable = str_replace('"','',$join);
else if (substr($join,0,5) != 'INNER') $query->from[$table] = "LEFT JOIN \"$table\" ON \"$table\".RecordID = \"{$baseTable}_versions\".RecordID AND \"$table\".Version = \"{$baseTable}_versions\".Version"; else if (substr($join,0,5) != 'INNER') $query->from[$table] = "LEFT JOIN \"$table\" ON \"$table\".RecordID = \"{$baseTable}_versions\".RecordID AND \"$table\".Version = \"{$baseTable}_versions\".Version";
$query->renameTable($table, $table . '_versions'); $query->renameTable($table, $table . '_versions');
} }
@ -635,7 +635,7 @@ class Versioned extends DataObjectDecorator {
function buildVersionSQL($filter = "", $sort = "") { function buildVersionSQL($filter = "", $sort = "") {
$query = $this->owner->extendedSQL($filter,$sort); $query = $this->owner->extendedSQL($filter,$sort);
foreach($query->from as $table => $join) { foreach($query->from as $table => $join) {
if($join[0] == '\"') $baseTable = str_replace('\"','',$join); if($join[0] == '"') $baseTable = str_replace('"','',$join);
else $query->from[$table] = "LEFT JOIN \"$table\" ON \"$table\".RecordID = \"{$baseTable}_versions\".RecordID AND \"$table\".Version = \"{$baseTable}_versions\".Version"; else $query->from[$table] = "LEFT JOIN \"$table\" ON \"$table\".RecordID = \"{$baseTable}_versions\".RecordID AND \"$table\".Version = \"{$baseTable}_versions\".Version";
$query->renameTable($table, $table . '_versions'); $query->renameTable($table, $table . '_versions');
} }
@ -646,7 +646,7 @@ class Versioned extends DataObjectDecorator {
static function build_version_sql($className, $filter = "", $sort = "") { static function build_version_sql($className, $filter = "", $sort = "") {
$query = singleton($className)->extendedSQL($filter,$sort); $query = singleton($className)->extendedSQL($filter,$sort);
foreach($query->from as $table => $join) { foreach($query->from as $table => $join) {
if($join[0] == '\"') $baseTable = str_replace('"','',$join); if($join[0] == '"') $baseTable = str_replace('"','',$join);
else $query->from[$table] = "LEFT JOIN \"$table\" ON \"$table\".RecordID = \"{$baseTable}_versions\".RecordID AND \"$table\".Version = \"{$baseTable}_versions\".Version"; else $query->from[$table] = "LEFT JOIN \"$table\" ON \"$table\".RecordID = \"{$baseTable}_versions\".RecordID AND \"$table\".Version = \"{$baseTable}_versions\".Version";
$query->renameTable($table, $table . '_versions'); $query->renameTable($table, $table . '_versions');
} }
@ -765,4 +765,4 @@ class Versioned_Version extends ViewableData {
} }
} }
?> ?>

View File

@ -47,7 +47,7 @@ class Boolean extends DBField {
* If necessary, this should include quotes. * If necessary, this should include quotes.
*/ */
function prepValueForDB($value) { function prepValueForDB($value) {
if($value === true || $value === 1) { if($value === true || $value === 1 || $value === '1') {
return "'1'"; return "'1'";
} if(!$value || !is_numeric($value)) { } if(!$value || !is_numeric($value)) {
return "'0'"; return "'0'";

View File

@ -176,17 +176,17 @@ class SearchForm extends Form {
$baseClass = reset($queryContent->from); $baseClass = reset($queryContent->from);
// There's no need to do all that joining // There's no need to do all that joining
$queryContent->from = array(str_replace(array('`','"'),'',$baseClass) => $baseClass); $queryContent->from = array(str_replace(array('`','"'),'',$baseClass) => $baseClass);
$queryContent->select = array("\"ClassName\"","\"$baseClass\".\"ID\"","\"ParentID\"","\"Title\"", $queryContent->select = array("\"ClassName\"","$baseClass.\"ID\"","\"ParentID\"","\"Title\"",
"\"URLSegment\"","\"Content\"","\"LastEdited\"","\"Created\"","_utf8'' AS \"Filename\"", "\"URLSegment\"","\"Content\"","\"LastEdited\"","\"Created\"","'' AS \"Filename\"",
"_utf8'' AS \"Name\"", "$relevanceContent AS \"Relevance\"", "\"CanViewType\""); "'' AS \"Name\"", "$relevanceContent AS \"Relevance\"", "\"CanViewType\"");
$queryContent->orderby = null; $queryContent->orderby = null;
$queryFiles = singleton('File')->extendedSQL($notMatch . $matchFile . $fileFilter, ""); $queryFiles = singleton('File')->extendedSQL($notMatch . $matchFile . $fileFilter, "");
$baseClass = reset($queryFiles->from); $baseClass = reset($queryFiles->from);
// There's no need to do all that joining // There's no need to do all that joining
$queryFiles->from = array(str_replace(array('`','"'),'',$baseClass) => $baseClass); $queryFiles->from = array(str_replace(array('`','"'),'',$baseClass) => $baseClass);
$queryFiles->select = array("\"ClassName\"","\"$baseClass\".\"ID\"","_utf8'' AS \"ParentID\"","\"Title\"", $queryFiles->select = array("\"ClassName\"","$baseClass.\"ID\"","'' AS \"ParentID\"","\"Title\"",
"_utf8'' AS \"URLSegment\"","\"Content\"","\"LastEdited\"","\"Created\"","\"Filename\"","\"Name\"", "'' AS \"URLSegment\"","\"Content\"","\"LastEdited\"","\"Created\"","\"Filename\"","\"Name\"",
"$relevanceFile AS \"Relevance\"","NULL AS \"CanViewType\""); "$relevanceFile AS \"Relevance\"","NULL AS \"CanViewType\"");
$queryFiles->orderby = null; $queryFiles->orderby = null;

View File

@ -6,24 +6,24 @@ class ControllerTest extends SapphireTest {
function testDefaultAction() { function testDefaultAction() {
/* For a controller with a template, the default action will simple run that template. */ /* For a controller with a template, the default action will simple run that template. */
$response = Director::test("ControllerTest_Controller/"); $response = Director::test("ControllerTest_Controller/");
$this->assertEquals("This is the main template. Content is 'default content'.", $response->getBody()); $this->assertRegExp("/This is the main template. Content is 'default content'/", $response->getBody());
} }
function testMethodActions() { function testMethodActions() {
/* The Action can refer to a method that is called on the object. If a method returns an array, then it will be /* The Action can refer to a method that is called on the object. If a method returns an array, then it will be
used to customise the template data */ used to customise the template data */
$response = Director::test("ControllerTest_Controller/methodaction"); $response = Director::test("ControllerTest_Controller/methodaction");
$this->assertEquals("This is the main template. Content is 'methodaction content'.", $response->getBody()); $this->assertRegExp("/This is the main template. Content is 'methodaction content'./", $response->getBody());
/* If the method just returns a string, then that will be used as the response */ /* If the method just returns a string, then that will be used as the response */
$response = Director::test("ControllerTest_Controller/stringaction"); $response = Director::test("ControllerTest_Controller/stringaction");
$this->assertEquals("stringaction was called.", $response->getBody()); $this->assertRegExp("/stringaction was called./", $response->getBody());
} }
function testTemplateActions() { function testTemplateActions() {
/* If there is no method, it can be used to point to an alternative template. */ /* If there is no method, it can be used to point to an alternative template. */
$response = Director::test("ControllerTest_Controller/templateaction"); $response = Director::test("ControllerTest_Controller/templateaction");
$this->assertEquals("This is the template for templateaction. Content is 'default content'.", $response->getBody()); $this->assertRegExp("/This is the template for templateaction. Content is 'default content'./", $response->getBody());
} }
function testAllowedActions() { function testAllowedActions() {

View File

@ -85,7 +85,7 @@ class SQLQueryTest extends SapphireTest {
$query = new SQLQuery(); $query = new SQLQuery();
$query->from[] = "MyTable"; $query->from[] = "MyTable";
$query->limit(array('limit'=>99, 'start'=>97)); $query->limit(array('limit'=>99, 'start'=>97));
$this->assertEquals("SELECT * FROM MyTable LIMIT 97,99", $query->sql()); $this->assertEquals("SELECT * FROM MyTable LIMIT 99 OFFSET 97", $query->sql());
} }
function testSelectWithOrderbyClause() { function testSelectWithOrderbyClause() {

View File

@ -10,7 +10,7 @@ class SSViewerTest extends SapphireTest {
)); ));
$result = $data->renderWith("SSViewerTestPartialTemplate"); $result = $data->renderWith("SSViewerTestPartialTemplate");
$this->assertEquals('Test partial template: var value', $result); $this->assertEquals('Test partial template: var value', trim(preg_replace("/<!--.*-->/U",'',$result)));
} }
function testRequirements() { function testRequirements() {
@ -41,6 +41,6 @@ SS
); );
$output = $viewer->process(new ArrayData(array())); $output = $viewer->process(new ArrayData(array()));
$this->assertEquals("This is my templateThis is some contentThis is the final content", $output); $this->assertEquals("This is my templateThis is some contentThis is the final content", preg_replace("/\n?<!--.*-->\n?/U",'',$output));
} }
} }

View File

@ -32,16 +32,16 @@ class DBFieldTest extends SapphireTest {
$this->assertEquals('1', singleton('Decimal')->prepValueForDB('1')); $this->assertEquals('1', singleton('Decimal')->prepValueForDB('1'));
/* Boolean behaviour, asserting we have 0 */ /* Boolean behaviour, asserting we have 0 */
$this->assertEquals('0', singleton('Boolean')->prepValueForDB(0)); $this->assertEquals("'0'", singleton('Boolean')->prepValueForDB(0));
$this->assertEquals('0', singleton('Boolean')->prepValueForDB(null)); $this->assertEquals("'0'", singleton('Boolean')->prepValueForDB(null));
$this->assertEquals('0', singleton('Boolean')->prepValueForDB(false)); $this->assertEquals("'0'", singleton('Boolean')->prepValueForDB(false));
$this->assertEquals('0', singleton('Boolean')->prepValueForDB('')); $this->assertEquals("'0'", singleton('Boolean')->prepValueForDB(''));
$this->assertEquals('0', singleton('Boolean')->prepValueForDB('0')); $this->assertEquals("'0'", singleton('Boolean')->prepValueForDB('0'));
/* Boolean behaviour, asserting we have 1 */ /* Boolean behaviour, asserting we have 1 */
$this->assertEquals('1', singleton('Boolean')->prepValueForDB(true)); $this->assertEquals("'1'", singleton('Boolean')->prepValueForDB(true));
$this->assertEquals('1', singleton('Boolean')->prepValueForDB(1)); $this->assertEquals("'1'", singleton('Boolean')->prepValueForDB(1));
$this->assertEquals('1', singleton('Boolean')->prepValueForDB('1')); $this->assertEquals("'1'", singleton('Boolean')->prepValueForDB('1'));
/* Varchar behaviour */ /* Varchar behaviour */
$this->assertEquals("'0'", singleton('Varchar')->prepValueForDB(0)); $this->assertEquals("'0'", singleton('Varchar')->prepValueForDB(0));

View File

@ -44,7 +44,6 @@ class RequirementsTest extends SapphireTest {
$html = Requirements::includeInHTML(false, self::$html_template); $html = Requirements::includeInHTML(false, self::$html_template);
/* COMBINED JAVASCRIPT FILE IS INCLUDED IN HTML HEADER */ /* COMBINED JAVASCRIPT FILE IS INCLUDED IN HTML HEADER */
Debug::message($html);
$this->assertTrue((bool)preg_match('/src=".*\/RequirementsTest_bc\.js/', $html), 'combined javascript file is included in html header'); $this->assertTrue((bool)preg_match('/src=".*\/RequirementsTest_bc\.js/', $html), 'combined javascript file is included in html header');
/* COMBINED JAVASCRIPT FILE EXISTS */ /* COMBINED JAVASCRIPT FILE EXISTS */