From 664903433deea72c2ae0f0e644587a1e911d5080 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Thu, 5 Jul 2012 16:20:18 +0200 Subject: [PATCH] Mark DBDatetimeTest skipped on wrong offsets, rather than error out. While well-intentioned, this test keeps causing problems due to wrong timezone settings in test mode. It shouldn't completely abort test execution, since its more of an environment sanity check than a failed test. Refactored to mark test skipped (regardless of offset, as long as its greater than 5 seconds). And skipping tests altogether on SQLite3 with new supportsTimezoneOverride() check. SapphireTest->setUp() sets the PHP timezone to UTC (see 59547745), but SQLite doesn't support this for a DB connection. Since changing it on a global UNIX system level is infeasible, the tests need to be skipped. --- tests/model/DbDatetimeTest.php | 168 ++++++++++++++++----------------- 1 file changed, 82 insertions(+), 86 deletions(-) diff --git a/tests/model/DbDatetimeTest.php b/tests/model/DbDatetimeTest.php index 3b351034aad..7e0ffcd4d5c 100644 --- a/tests/model/DbDatetimeTest.php +++ b/tests/model/DbDatetimeTest.php @@ -6,20 +6,16 @@ class DbDatetimeTest extends FunctionalTest { protected $extraDataObjects = array('DbDatetimeTest_Team'); - private static $offset = 0; // number of seconds of php and db time are out of sync - private static $offset_thresholds = array( // throw an error if the offset exceeds 30 minutes - E_USER_ERROR => 1800, - E_USER_NOTICE => 5, - ); + protected $offset; + + protected $adapter; - private $adapter; - /** * Check if dates match more or less. This takes into the account the db query * can overflow to the next second giving offset readings. */ - private function matchesRoughly($date1, $date2, $comment = '') { - $allowedDifference = 5 + abs(self::$offset); // seconds + private function matchesRoughly($date1, $date2, $comment = '', $offset) { + $allowedDifference = 5 + abs($offset); // seconds $time1 = is_numeric($date1) ? $date1 : strtotime($date1); $time2 = is_numeric($date2) ? $date2 : strtotime($date2); @@ -31,104 +27,104 @@ private function getDbNow() { $query = 'SELECT ' . $this->adapter->formattedDatetimeClause('now', '%U'); return DB::query($query)->value(); } - - function setUpOnce() { - parent::setUpOnce(); - - self::$offset = time() - strtotime(DB::query('SELECT ' . DB::getConn()->now())->value()); - foreach(self::$offset_thresholds as $code => $offset) { - if(abs(self::$offset) > $offset) { - if($code == E_USER_NOTICE) { - Debug::show('The time of the database is out of sync with the webserver by ' . abs(self::$offset) . ' seconds.'); - } else { - trigger_error('The time of the database is out of sync with the webserver by ' . abs(self::$offset) . ' seconds.', $code); - } - break; - } + + /** + * Needs to be run within a test*() context. + * + * @return Int Offset in seconds + */ + private function checkPreconditions() { + // number of seconds of php and db time are out of sync + $offset = time() - strtotime(DB::query('SELECT ' . DB::getConn()->now())->value()); + $threshold = 5; // seconds + + if($offset > 5) { + $this->markTestSkipped('The time of the database is out of sync with the webserver by ' . abs($offset) . ' seconds.'); + } + + if(method_exists($this->adapter, 'supportsTimezoneOverride') && !$this->adapter->supportsTimezoneOverride()) { + $this->markTestSkipped("Database doesn't support timezone overrides"); } + + return $offset; } function setUp() { parent::setUp(); $this->adapter = DB::getConn(); - $this->supportDbDatetime = method_exists($this->adapter, 'datetimeIntervalClause'); } function testCorrectNow() { - if($this->supportDbDatetime) { - $clause = $this->adapter->formattedDatetimeClause('now', '%U'); - $result = DB::query('SELECT ' . $clause)->value(); - $this->assertRegExp('/^\d*$/', (string) $result); - $this->assertTrue($result>0); - } + $offset = $this->checkPreconditions(); + + $clause = $this->adapter->formattedDatetimeClause('now', '%U'); + $result = DB::query('SELECT ' . $clause)->value(); + $this->assertRegExp('/^\d*$/', (string) $result); + $this->assertTrue($result>0); } function testDbDatetimeFormat() { - if($this->supportDbDatetime) { - $clause = $this->adapter->formattedDatetimeClause('1973-10-14 10:30:00', '%H:%i, %d/%m/%Y'); - $result = DB::query('SELECT ' . $clause)->value(); - $this->matchesRoughly($result, date('H:i, d/m/Y', strtotime('1973-10-14 10:30:00')), 'nice literal time'); - - $clause = $this->adapter->formattedDatetimeClause('now', '%d'); - $result = DB::query('SELECT ' . $clause)->value(); - $this->matchesRoughly($result, date('d', $this->getDbNow()), 'todays day'); - - $clause = $this->adapter->formattedDatetimeClause('"Created"', '%U') . ' AS test FROM "DbDateTimeTest_Team"'; - $result = DB::query('SELECT ' . $clause)->value(); - $this->matchesRoughly($result, strtotime(DataObject::get_one('DbDateTimeTest_Team')->Created), 'fixture ->Created as timestamp'); - } + $offset = $this->checkPreconditions(); + + $clause = $this->adapter->formattedDatetimeClause('1973-10-14 10:30:00', '%H:%i, %d/%m/%Y'); + $result = DB::query('SELECT ' . $clause)->value(); + $this->matchesRoughly($result, date('H:i, d/m/Y', strtotime('1973-10-14 10:30:00')), 'nice literal time', $offset); + + $clause = $this->adapter->formattedDatetimeClause('now', '%d'); + $result = DB::query('SELECT ' . $clause)->value(); + $this->matchesRoughly($result, date('d', $this->getDbNow()), 'todays day', $offset); + + $clause = $this->adapter->formattedDatetimeClause('"Created"', '%U') . ' AS test FROM "DbDateTimeTest_Team"'; + $result = DB::query('SELECT ' . $clause)->value(); + $this->matchesRoughly($result, strtotime(DataObject::get_one('DbDateTimeTest_Team')->Created), 'fixture ->Created as timestamp', $offset); } function testDbDatetimeInterval() { - if($this->supportDbDatetime) { - - $clause = $this->adapter->datetimeIntervalClause('1973-10-14 10:30:00', '+18 Years'); - $result = DB::query('SELECT ' . $clause)->value(); - $this->matchesRoughly($result, '1991-10-14 10:30:00', 'add 18 years'); + $offset = $this->checkPreconditions(); - $clause = $this->adapter->datetimeIntervalClause('now', '+1 Day'); - $result = DB::query('SELECT ' . $clause)->value(); - $this->matchesRoughly($result, date('Y-m-d H:i:s', strtotime('+1 Day', $this->getDbNow())), 'tomorrow'); + $clause = $this->adapter->datetimeIntervalClause('1973-10-14 10:30:00', '+18 Years'); + $result = DB::query('SELECT ' . $clause)->value(); + $this->matchesRoughly($result, '1991-10-14 10:30:00', 'add 18 years', $offset); - $query = new SQLQuery(); - $query->setSelect(array()); - $query->selectField($this->adapter->datetimeIntervalClause('"Created"', '-15 Minutes'), 'test') - ->setFrom('"DbDateTimeTest_Team"') - ->setLimit(1); + $clause = $this->adapter->datetimeIntervalClause('now', '+1 Day'); + $result = DB::query('SELECT ' . $clause)->value(); + $this->matchesRoughly($result, date('Y-m-d H:i:s', strtotime('+1 Day', $this->getDbNow())), 'tomorrow', $offset); - $result = $query->execute()->value(); - $this->matchesRoughly($result, date('Y-m-d H:i:s', strtotime(DataObject::get_one('DbDateTimeTest_Team')->Created) - 900), '15 Minutes before creating fixture'); + $query = new SQLQuery(); + $query->setSelect(array()); + $query->selectField($this->adapter->datetimeIntervalClause('"Created"', '-15 Minutes'), 'test') + ->setFrom('"DbDateTimeTest_Team"') + ->setLimit(1); - } + $result = $query->execute()->value(); + $this->matchesRoughly($result, date('Y-m-d H:i:s', strtotime(DataObject::get_one('DbDateTimeTest_Team')->Created) - 900), '15 Minutes before creating fixture', $offset); } function testDbDatetimeDifference() { - if($this->supportDbDatetime) { - - $clause = $this->adapter->datetimeDifferenceClause('1974-10-14 10:30:00', '1973-10-14 10:30:00'); - $result = DB::query('SELECT ' . $clause)->value(); - $this->matchesRoughly($result/86400, 365, '1974 - 1973 = 365 * 86400 sec'); - - $clause = $this->adapter->datetimeDifferenceClause(date('Y-m-d H:i:s', strtotime('-15 seconds')), 'now'); - $result = DB::query('SELECT ' . $clause)->value(); - $this->matchesRoughly($result, -15, '15 seconds ago - now'); - - $clause = $this->adapter->datetimeDifferenceClause('now', $this->adapter->datetimeIntervalClause('now', '+45 Minutes')); - $result = DB::query('SELECT ' . $clause)->value(); - $this->matchesRoughly($result, -45 * 60, 'now - 45 minutes ahead'); - - $query = new SQLQuery(); - $query->setSelect(array()); - $query->selectField($this->adapter->datetimeDifferenceClause('"LastEdited"', '"Created"'), 'test') - ->setFrom('"DbDateTimeTest_Team"') - ->setLimit(1); - - $result = $query->execute()->value(); - $lastedited = Dataobject::get_one('DbDateTimeTest_Team')->LastEdited; - $created = Dataobject::get_one('DbDateTimeTest_Team')->Created; - $this->matchesRoughly($result, strtotime($lastedited) - strtotime($created), 'age of HomePage record in seconds since unix epoc'); - - } + $offset = $this->checkPreconditions(); + + $clause = $this->adapter->datetimeDifferenceClause('1974-10-14 10:30:00', '1973-10-14 10:30:00'); + $result = DB::query('SELECT ' . $clause)->value(); + $this->matchesRoughly($result/86400, 365, '1974 - 1973 = 365 * 86400 sec', $offset); + + $clause = $this->adapter->datetimeDifferenceClause(date('Y-m-d H:i:s', strtotime('-15 seconds')), 'now'); + $result = DB::query('SELECT ' . $clause)->value(); + $this->matchesRoughly($result, -15, '15 seconds ago - now', $offset); + + $clause = $this->adapter->datetimeDifferenceClause('now', $this->adapter->datetimeIntervalClause('now', '+45 Minutes')); + $result = DB::query('SELECT ' . $clause)->value(); + $this->matchesRoughly($result, -45 * 60, 'now - 45 minutes ahead', $offset); + + $query = new SQLQuery(); + $query->setSelect(array()); + $query->selectField($this->adapter->datetimeDifferenceClause('"LastEdited"', '"Created"'), 'test') + ->setFrom('"DbDateTimeTest_Team"') + ->setLimit(1); + + $result = $query->execute()->value(); + $lastedited = Dataobject::get_one('DbDateTimeTest_Team')->LastEdited; + $created = Dataobject::get_one('DbDateTimeTest_Team')->Created; + $this->matchesRoughly($result, strtotime($lastedited) - strtotime($created), 'age of HomePage record in seconds since unix epoc', $offset); } } @@ -137,4 +133,4 @@ class DbDateTimeTest_Team extends DataObject implements TestOnly { static $db = array( 'Title' => 'Varchar' ); -} +} \ No newline at end of file