=== modified file 'modules/simpletest/drupal_web_test_case.php' --- modules/simpletest/drupal_web_test_case.php 2008-08-23 07:42:54 +0000 +++ modules/simpletest/drupal_web_test_case.php 2008-08-28 05:14:32 +0000 @@ -20,9 +20,12 @@ class DrupalWebTestCase { protected $db_prefix_original; protected $original_file_directory; - var $_results = array('#pass' => 0, '#fail' => 0, '#exception' => 0); + var $_results = array('#pass' => 0, '#fail' => 0, '#exception' => 0, '#unexpected pass' => 0, '#expected fail' => 0); + var $_assertions = array(); + var $expectedFail = FALSE; + /** * Constructor for DrupalWebTestCase. * @@ -34,6 +37,18 @@ class DrupalWebTestCase { } /** + * The next assert is expected to fail. + * + * Use $this->expectedFail->assert... to mark the assert as an expected fail. + * If your test reveals a bug then use this function. + */ + protected function expectedFail() { + $this->expectedFail = TRUE; + return $this; + } + + + /** * This function stores the assert. Do not call directly. * * @param $status @@ -52,6 +67,13 @@ class DrupalWebTestCase { */ protected function _assert($status, $message = '', $group = 'Other', $custom_caller = NULL) { global $db_prefix; + if ($this->expectedFail) { + $this->expectedFail = FALSE; + $message .= t('This is expected to fail due to a known bug.'); + if (is_bool($status)) { + $status = $status ? 'unexpected pass' : 'expected fail'; + } + } if (is_bool($status)) { $status = $status ? 'pass' : 'fail'; } @@ -72,13 +94,13 @@ class DrupalWebTestCase { $db_prefix = $this->db_prefix_original; db_insert('simpletest')->fields(array( 'test_id' => $this->test_id, - 'test_class' => get_class($this), - 'status' => $status, - 'message' => substr($message, 0, 255), // Some messages are too long for the database. - 'message_group' => $group, - 'caller' => $function['function'], - 'line' => $function['line'], - 'file' => $function['file'], + 'test_class' => get_class($this), + 'status' => $status, + 'message' => substr($message, 0, 255), // Some messages are too long for the database. + 'message_group' => $group, + 'caller' => $function['function'], + 'line' => $function['line'], + 'file' => $function['file'], ))->execute(); $this->_assertions[] = array( 'status' => $status, @@ -405,7 +427,7 @@ class DrupalWebTestCase { node_types_rebuild(); $this->assertEqual($saved_type, SAVED_NEW, t('Created content type %type.', array('%type' => $type->type))); - + // Reset permissions so that permissions for this content type are available. $this->checkPermissions(array(), TRUE); @@ -645,7 +667,7 @@ class DrupalWebTestCase { // Generate temporary prefixed database to ensure that tests have a clean starting point. $db_prefix = 'simpletest' . mt_rand(1000, 1000000); - + include_once './includes/install.inc'; drupal_install_system(); @@ -659,7 +681,7 @@ class DrupalWebTestCase { // stale data for the previous run's database prefix and all // calls to it will fail. drupal_get_schema(NULL, TRUE); - + // Run default profile tasks. $task = 'profile'; default_profile_tasks($task, ''); === modified file 'modules/simpletest/simpletest.css' --- modules/simpletest/simpletest.css 2008-06-24 21:51:02 +0000 +++ modules/simpletest/simpletest.css 2008-08-27 20:23:51 +0000 @@ -24,11 +24,13 @@ table#simpletest-form-table tr.simpletes background-color: #EDF5FA !important; } -div.simpletest-pass { +div.simpletest-pass, +div.simpletest-expected-fail { color: #33a333; } -div.simpletest-fail { +div.simpletest-fail, +div.simpletest-unexpected-pass { color: #a30000; } === modified file 'modules/simpletest/simpletest.install' --- modules/simpletest/simpletest.install 2008-08-16 20:57:14 +0000 +++ modules/simpletest/simpletest.install 2008-08-27 20:10:03 +0000 @@ -160,7 +160,7 @@ function simpletest_schema() { ), 'status' => array( 'type' => 'varchar', - 'length' => 9, + 'length' => 17 'not null' => TRUE, 'default' => '', 'description' => t('Message status. Core understands pass, fail, exception.'), === modified file 'modules/simpletest/simpletest.module' --- modules/simpletest/simpletest.module 2008-08-21 19:36:35 +0000 +++ modules/simpletest/simpletest.module 2008-08-28 05:13:09 +0000 @@ -70,6 +70,8 @@ function simpletest_test_form() { '#pass' => 0, '#fail' => 0, '#exception' => 0, + '#unexpected pass' => 0, + '#expected fail' => 0, '#weight' => -10, ); $form['summary'] = $summary; @@ -79,6 +81,8 @@ function simpletest_test_form() { 'pass' => theme('image', 'misc/watchdog-ok.png'), 'fail' => theme('image', 'misc/watchdog-error.png'), 'exception' => theme('image', 'misc/watchdog-warning.png'), + 'unexpected pass' => theme('image', 'misc/watchdog-error.png'), + 'expected fail' => theme('image', 'misc/watchdog-warning.png'), ); $header = array(t('Message'), t('Group'), t('Filename'), t('Line'), t('Function'), array('colspan' => 2, 'data' => t('Status'))); while ($result = db_fetch_object($results)) { @@ -93,7 +97,8 @@ function simpletest_test_form() { $element['summary'] = $summary; } $status = $result->status; - // This reporter can only handle pass, fail and exception. + // This reporter can only handle pass, fail, exception, unexpected pass + // and expected fail. if (isset($map[$status])) { $element['#title'] = $info['name']; $status_index = '#'. $status; @@ -109,7 +114,7 @@ function simpletest_test_form() { $result->caller, $map[$status], ), - 'class' => "simpletest-$status", + 'class' => str_replace(' ', '-', "simpletest-$status"), ); } unset($element); @@ -127,7 +132,7 @@ function simpletest_test_form() { $group_ok = TRUE; foreach ($elements as $class => &$element) { $info = $uncategorized_tests[$class]->getInfo(); - $ok = $element['summary']['#fail'] + $element['summary']['#exception'] == 0; + $ok = $element['summary']['#fail'] + $element['summary']['#exception'] + $element['summary']['#unexpected pass'] == 0; $element += array( '#type' => 'fieldset', '#collapsible' => TRUE, @@ -270,10 +275,12 @@ function theme_simpletest_result_summary } function _simpletest_format_summary_line($summary) { - return t('@pass, @fail, @exception', array( + return t('@pass, @fail, @exception, @unexpected_pass, @expected_fail', array( '@pass' => format_plural(isset($summary['#pass']) ? $summary['#pass'] : 0, '1 pass', '@count passes'), '@fail' => format_plural(isset($summary['#fail']) ? $summary['#fail'] : 0, '1 fail', '@count fails'), '@exception' => format_plural(isset($summary['#exception']) ? $summary['#exception'] : 0, '1 exception', '@count exceptions'), + '@unexpected_pass' => format_plural(isset($summary['#unexpected pass']) ? $summary['#unexpected pass'] : 0, '1 unexpected pass', '@count unexpected passes'), + '@expected_fail' => format_plural(isset($summary['#expected fail']) ? $summary['#expected fail'] : 0, '1 expected fail', '@count unexpected fails'), )); } @@ -350,7 +357,7 @@ function _simpletest_batch_operation($te // First iteration: initialize working values. $test_list = $test_list_init; $context['sandbox']['max'] = count($test_list); - $test_results = array('#pass' => 0, '#fail' => 0, '#exception' => 0); + $test_results = array('#pass' => 0, '#fail' => 0, '#exception' => 0, '#unexpected pass', '#expected fail'); } else { // Nth iteration: get the current values where we last stored them. @@ -374,7 +381,8 @@ function _simpletest_batch_operation($te $test_results[$test_class]['#name'] = $info['name']; $items = array(); foreach (element_children($test_results) as $class) { - $items[] = '
' . t('@name: @summary', array('@name' => $test_results[$class]['#name'], '@summary' => _simpletest_format_summary_line($test_results[$class]))) . '
'; + $errors = $test_results[$class]['#fail'] + $test_results[$class]['#exception'] + $test_results[$class]['#unexpected pass']; + $items[] = '
' . t('@name: @summary', array('@name' => $test_results[$class]['#name'], '@summary' => _simpletest_format_summary_line($test_results[$class]))) . '
'; } $message = t('Processed test @num of @max - %test.', array('%test' => $info['name'], '@num' => $max - $size, '@max' => $max)); $message .= theme('item_list', $items); === modified file 'modules/simpletest/tests/cache.test' --- modules/simpletest/tests/cache.test 2008-08-14 09:18:28 +0000 +++ modules/simpletest/tests/cache.test 2008-08-27 20:14:00 +0000 @@ -233,4 +233,157 @@ class CacheClearCase extends CacheTestCa || $this->checkCacheExists('test_cid_clear2', $this->default_value), t('Two caches removed after clearing cid substring with wildcard true.')); } -} \ No newline at end of file +} + +class CacheExpiryCase extends CacheTestCase { + /** + * Implementation of getInfo(). + */ + function getInfo() { + return array( + 'name' => t('Cache expire test'), + 'description' => t('Check or the expiration of the cache is working properly'), + 'group' => t('Cache') + ); + } + + /** + * Implementation of setUp(). + */ + function setUp() { + $this->default_table = 'cache'; + $this->default_cid = 'test_expiry'; + $this->default_value = $this->randomName(10); + + parent::setUp(); + } + + /** + * testTemporaryNoLifetime() + * Tests the expiry of data when the $expire is set to CACHE_TEMPORARY and lifetime is off. + * - CACHE_TEMPORARY: Indicates that the item should be removed at the next + * general cache wipe. + */ + function testTemporaryNoLifetime() { + $this->setupLifetime(0); + cache_set($this->default_cid, $this->default_value, $this->default_table, CACHE_TEMPORARY); + + $this->assertCacheExists(t('Temporary cache data without lifetime exists before wipe.')); + + $user->cache = isset($user->cache) ? $user->cache +2 : time() + 2; + $this->assertCacheExists(t('Temporary cache without lifetime valid after user cache expiration.')); + $user->cache = $user->cache - 2; + + $this->generalWipe(); + $this->assertCacheRemoved(t('Temporary cache without lifetime does not exists after wipe.')); + } + + /** + * testTemporaryLifetime() + * Tests the expiry of data when the $expire is set to CACHE_TEMPORARY and lifetime is on. + * - CACHE_TEMPORARY: Indicates that the item should be removed at the next + * general cache wipe. + */ + function testTemporaryLifetime() { + $this->setupLifetime(5); + cache_set($this->default_cid, $this->default_value, $this->default_table, CACHE_TEMPORARY); + + $this->assertCacheExists(t('Temporary cache with lifetime data exists before wipe.')); + + $user->cache = isset($user->cache) ? $user->cache + 2 : time() + 2; + $this->assertCacheExists(t('Temporary cache without lifetime valid after user cache expiration.')); + $user->cache = $user->cache - 2; + + $this->generalWipe(); + $this->expectedFail()->assertCacheRemoved(t('Temporary cache with lifetime does not exists after wipe.')); + } + + /** + * testPermanentNoLifetime() + * Tests the expiry of data when the $expire is set to CACHE_PERMANENT and lifetime is off. + * - CACHE_PERMANENT: Indicates that the item should never be removed unless + * explicitly told to using cache_clear_all() with a cache ID. + */ + function testPermanentNoLifetime() { + $this->setupLifetime(0); + cache_set($this->default_cid, $this->default_value, $this->default_table, CACHE_PERMANENT); + + $this->assertCacheExists(t('Permanent cache data without lifetime exists before wipe.')); + + $user->cache = isset($user->cache) ? $user->cache + 2 : time() + 2; + $this->assertCacheExists(t('Permanent cache without lifetime valid after user cache expiration.')); + $user->cache = $user->cache - 2; + + $this->generalWipe(); + $this->assertCacheExists(t('Permanent cache without lifetime exists after wipe.')); + } + + /** + * testPermanentLifetime() + * Tests the expiry of data when the $expire is set to CACHE_PERMANENT and lifetime is on. + * - CACHE_PERMANENT: Indicates that the item should never be removed unless + * explicitly told to using cache_clear_all() with a cache ID. + */ + function testPermanentLifetime() { + $this->setupLifetime(5); + cache_set($this->default_cid, $this->default_value, $this->default_table, CACHE_PERMANENT); + + $this->assertCacheExists(t('Permanent cache data with lifetime exists before wipe.')); + + $user->cache = isset($user->cache) ? $user->cache + 2 : time() + 2; + $this->assertCacheExists(t('Permanent cache with lifetime valid after user cache expiration.')); + $user->cache = $user->cache - 2; + + $this->generalWipe(); + $this->assertCacheExists(t('Permanent cache with lifetime exists after wipe.')); + } + + /** + * testUnixTimestampNoLifetime() + * Tests the expiry of data when the $expire is set to unix timestamp and lifetime is off. + * - A Unix timestamp: Indicates that the item should be kept at least until + * the given time, after which it behaves like CACHE_TEMPORARY. + */ + function testUnixTimestampNoLifetime() { + $this->setupLifetime(0); + cache_set($this->default_cid, $this->default_value, $this->default_table, time() + 1); + + $this->assertCacheExists(t('Unit timestamp cache data without lifetime exists before wipe.')); + $this->generalWipe(); + $this->assertCacheExists(t('Unit timestamp cache without lifetime exists after wipe.')); + sleep(2); // expire + $this->assertCacheExists(t('Unit timestamp cache without lifetime exists after expiration.')); + + $user->cache = isset($user->cache) ? $user->cache + 2 : time() + 2; + $this->assertCacheExists(t('Unit timestamp cache without lifetime valid after user cache expiration.')); + $user->cache = $user->cache - 2; + + $this->generalWipe(); + $this->assertCacheRemoved(t('Unit timestamp cache without lifetime deleted after expiration and wipe.')); + } + + /** + * testUnixTimestampLifetime() + * Tests the expiry of data when the $expire is set to unix timestamp and lifetime is on. + * - A Unix timestamp: Indicates that the item should be kept at least until + * the given time, after which it behaves like CACHE_TEMPORARY. + */ + function testUnixTimestampLifetime() { + $this->setupLifetime(5); + cache_set($this->default_cid, $this->default_value, $this->default_table, time() + 1); + global $user; + + $this->assertCacheExists(t('Unit timestamp cache data without lifetime exists before wipe.')); + $this->generalWipe(); + $this->assertCacheExists(t('Unit timestamp cache with lifetime exists after wipe.')); + sleep(2); // expire + $this->assertCacheExists(t('Unit timestamp cache with lifetime exists after expiration.')); + + $user->cache = $user->cache + 2; + $this->assertCacheRemoved(t('Unit timestamp cache with lifetime not valid after user cache expiration.')); + $user->cache = $user->cache - 2; + + $this->generalWipe(); + $this->assertCacheRemoved(t('Unit timestamp cache with lifetime deleted after expiration and wipe.')); + } +}