From 3fed6c722cf5f66515cd82c765039fcd179aee0e Mon Sep 17 00:00:00 2001 From: Angie Byron Date: Sun, 1 Mar 2009 07:21:02 +0000 Subject: [PATCH] #364467 by alex_b: Fix remove followed by update aggregator items. --- modules/aggregator/aggregator.module | 1 + modules/aggregator/aggregator.test | 140 ++++++++++-------- modules/aggregator/aggregator_test.info | 7 + modules/aggregator/aggregator_test.module | 58 ++++++++ modules/aggregator/aggregator_test_rss091.xml | 30 ++++ 5 files changed, 175 insertions(+), 61 deletions(-) create mode 100644 modules/aggregator/aggregator_test.info create mode 100644 modules/aggregator/aggregator_test.module create mode 100644 modules/aggregator/aggregator_test_rss091.xml diff --git a/modules/aggregator/aggregator.module b/modules/aggregator/aggregator.module index 5791a9358dc..26f2ad12a03 100644 --- a/modules/aggregator/aggregator.module +++ b/modules/aggregator/aggregator.module @@ -515,6 +515,7 @@ function aggregator_remove($feed) { ->fields(array( 'checked' => 0, 'hash' => '', + 'etag' => '', 'modified' => 0, 'description' => $feed->description, 'image' => $feed->image, diff --git a/modules/aggregator/aggregator.test b/modules/aggregator/aggregator.test index 7000e908e8c..f2dd8bb36e3 100644 --- a/modules/aggregator/aggregator.test +++ b/modules/aggregator/aggregator.test @@ -5,7 +5,7 @@ class AggregatorTestCase extends DrupalWebTestCase { private static $prefix = 'simpletest_aggregator_'; function setUp() { - parent::setUp('aggregator'); + parent::setUp('aggregator', 'aggregator_test'); $web_user = $this->drupalCreateUser(array('administer news feeds', 'access news feeds', 'create article content')); $this->drupalLogin($web_user); } @@ -13,10 +13,15 @@ class AggregatorTestCase extends DrupalWebTestCase { /** * Create an aggregator feed (simulate form submission on admin/content/aggregator/add/feed). * - * @return $feed Full feed object if possible. + * @param $feed_url + * If given, feed will be created with this URL, otherwise /rss.xml will be used. + * @return $feed + * Full feed object if possible. + * + * @see getFeedEditArray() */ - function createFeed() { - $edit = $this->getFeedEditArray(); + function createFeed($feed_url = NULL) { + $edit = $this->getFeedEditArray($feed_url); $this->drupalPost('admin/content/aggregator/add/feed', $edit, t('Save')); $this->assertRaw(t('The feed %name has been added.', array('%name' => $edit['title'])), t('The feed !name has been added.', array('!name' => $edit['title']))); @@ -38,11 +43,16 @@ class AggregatorTestCase extends DrupalWebTestCase { /** * Return a randomly generated feed edit array. * - * @return array Feed array. + * @param $feed_url + * If given, feed will be created with this URL, otherwise /rss.xml will be used. + * @return + * A feed array. */ - function getFeedEditArray() { + function getFeedEditArray($feed_url = NULL) { $feed_name = $this->randomName(10, self::$prefix); - $feed_url = url(NULL, array('absolute' => TRUE)) . 'rss.xml?feed=' . $feed_name; + if (!$feed_url) { + $feed_url = $GLOBALS['base_url'] . '/rss.xml?feed=' . $feed_name; + } $edit = array( 'title' => $feed_name, 'url' => $feed_url, @@ -51,20 +61,30 @@ class AggregatorTestCase extends DrupalWebTestCase { return $edit; } + /** + * Return the count of the randomly created feed array. + * + * @return + * Number of feed items on default feed created by createFeed(). + */ + function getDefaultFeedItemCount() { + // Our tests are based off of rss.xml, so let's find out how many elements should be related. + $feed_count = db_query_range('SELECT COUNT(*) FROM {node} n WHERE n.promote = 1 AND n.status = 1', 0, variable_get('feed_default_items', 10))->fetchField(); + return $feed_count > 10 ? 10 : $feed_count; + } + /** * Update feed items (simulate click to admin/content/aggregator/update/$fid). * - * @param object $feed Feed object representing the feed. + * @param $feed + * Feed object representing the feed. + * @param $expected_count + * Expected number of feed items. */ - function updateFeedItems(&$feed) { + function updateFeedItems(&$feed, $expected_count) { // First, let's ensure we can get to the rss xml. - $this->drupalGet('rss.xml'); - $this->assertResponse(200, t('rss.xml is reachable.')); - - // Our tests are based off of rss.xml, so let's find out how many elements should be related. - // @todo: remove db_rewrite_sql() when possible - $feed_count = db_query_range(db_rewrite_sql('SELECT COUNT(*) FROM {node} n WHERE n.promote = 1 AND n.status = 1'), 0, variable_get('feed_default_items', 10))->fetchField(); - $feed_count = $feed_count > 10 ? 10 : $feed_count; + $this->drupalGet($feed->url); + $this->assertResponse(200, t('!url is reachable.', array('!url' => $feed->url))); // Refresh the feed (simulated link click). $this->drupalGet('admin/content/aggregator/update/' . $feed->fid); @@ -77,7 +97,7 @@ class AggregatorTestCase extends DrupalWebTestCase { $feed->items[] = $item->iid; } $feed->item_count = count($feed->items); - $this->assertEqual($feed_count, $feed->item_count, t('Total items in feed equal to the total items in database (!val1 != !val2)', array('!val1' => $feed_count, '!val2' => $feed->item_count))); + $this->assertEqual($expected_count, $feed->item_count, t('Total items in feed equal to the total items in database (!val1 != !val2)', array('!val1' => $expected_count, '!val2' => $feed->item_count))); } /** @@ -90,6 +110,22 @@ class AggregatorTestCase extends DrupalWebTestCase { $this->assertRaw(t('The news items from %title have been removed.', array('%title' => $feed->title)), t('Feed items removed.')); } + /** + * Add and remove feed items and ensure that the count is zero. + * + * @param $feed + * Feed object representing the feed. + * @param $expected_count + * Expected number of feed items. + */ + function updateAndRemove($feed, $expected_count) { + $this->updateFeedItems($feed, $expected_count); + $this->assertText('There is new syndicated content from'); + $this->removeFeedItems($feed); + $count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(); + $this->assertTrue($count == 0); + } + /** * Pull feed categories from aggregator_category_feed table. * @@ -192,36 +228,7 @@ EOF; } function getRSS091Sample() { - $feed = << - - - Example - http://example.com - Example updates - en-us - Copyright 2000, Example team. - editor@example.com - webmaster@example.com - - Example - http://example.com/images/druplicon.png - http://example.com - 88 - 100 - Example updates - - - Example turns one - http://example.com/example-turns-one - Example turns one. - - - -EOT; - - $path = file_directory_path() . '/rss091.xml'; - return file_unmanaged_save_data($feed, $path); + return $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'aggregator') . '/aggregator_test_rss091.xml'; } function createSampleNodes() { @@ -352,7 +359,7 @@ class UpdateFeedItemTestCase extends AggregatorTestCase { // Create a feed and test updating feed items if possible. $feed = $this->createFeed(); if (!empty($feed)) { - $this->updateFeedItems($feed); + $this->updateFeedItems($feed, $this->getDefaultFeedItemCount()); $this->removeFeedItems($feed); } @@ -362,8 +369,9 @@ class UpdateFeedItemTestCase extends AggregatorTestCase { // Test updating feed items without valid timestamp information. $edit = array( 'title' => "Feed without publish timestamp", - 'url' => file_create_url($this->getRSS091Sample()), + 'url' => $this->getRSS091Sample(), ); + $this->drupalGet($edit['url']); $this->assertResponse(array(200), t('URL !url is accessible', array('!url' => $edit['url']))); @@ -407,18 +415,28 @@ class RemoveFeedItemTestCase extends AggregatorTestCase { * Test running "remove items" from the 'admin/content/aggregator' page. */ function testRemoveFeedItem() { - $this->createSampleNodes(); + // Create a bunch of test feeds. + $feed_urls = array(); + // No last-modified, no etag. + $feed_urls[] = url('aggregator/test-feed', array('absolute' => TRUE)); + // Last-modified, but no etag. + $feed_urls[] = url('aggregator/test-feed/1', array('absolute' => TRUE)); + // No Last-modified, but etag. + $feed_urls[] = url('aggregator/test-feed/0/1', array('absolute' => TRUE)); + // Last-modified and etag. + $feed_urls[] = url('aggregator/test-feed/1/1', array('absolute' => TRUE)); - $feed = $this->createFeed(); - - // Add and remove feed items and ensure that the count is zero. - $this->updateFeedItems($feed); - $this->removeFeedItems($feed); - $count = db_query('SELECT COUNT(*) FROM {aggregator_item} WHERE fid = :fid', array(':fid' => $feed->fid))->fetchField(); - $this->assertTrue($count == 0); - - // Delete feed. - $this->deleteFeed($feed); + foreach ($feed_urls as $feed_url) { + $feed = $this->createFeed($feed_url); + // Update and remove items two times in a row to make sure that removal + // resets all 'modified' information (modified, etag, hash) and allows for + // immediate update. + $this->updateAndRemove($feed, 2); + $this->updateAndRemove($feed, 2); + $this->updateAndRemove($feed, 2); + // Delete feed. + $this->deleteFeed($feed); + } } } @@ -459,7 +477,7 @@ class CategorizeFeedItemTestCase extends AggregatorTestCase { 'fid' => $feed->fid, )) ->execute(); - $this->updateFeedItems($feed); + $this->updateFeedItems($feed, $this->getDefaultFeedItemCount()); $this->getFeedCategories($feed); $this->assertTrue(!empty($feed->categories), t('The category found in the feed.')); diff --git a/modules/aggregator/aggregator_test.info b/modules/aggregator/aggregator_test.info new file mode 100644 index 00000000000..d07ed900b38 --- /dev/null +++ b/modules/aggregator/aggregator_test.info @@ -0,0 +1,7 @@ +name = "Aggregator module tests" +description = "Support module for aggregator related testing." +package = Testing +version = VERSION +core = 7.x +files[] = aggregator_test.module +hidden = TRUE diff --git a/modules/aggregator/aggregator_test.module b/modules/aggregator/aggregator_test.module new file mode 100644 index 00000000000..e632aac886e --- /dev/null +++ b/modules/aggregator/aggregator_test.module @@ -0,0 +1,58 @@ + 'Test feed static last modified date', + 'description' => "A cached test feed with a static last modified date.", + 'page callback' => 'aggregator_test_feed', + 'access arguments' => array('access content'), + ); + return $items; +} + +/** + * Page callback. Generates a test feed and simulates last-modified and etags. + * + * @param $use_last_modified + * Set TRUE to send a last modified header. + * @param $use_etag + * Set TRUE to send an etag. + */ +function aggregator_test_feed($use_last_modified = FALSE, $use_etag = FALSE) { + $last_modified = strtotime('Sun, 19 Nov 1978 05:00:00 GMT'); + $etag = md5($last_modified); + + $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) : FALSE; + $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : FALSE; + + // Send appropriate response. We respond with a 304 not modified on either + // etag or on last modified. + if ($use_last_modified) { + drupal_set_header("Last-Modified: " . gmdate(DATE_RFC1123, $last_modified)); + } + if ($use_etag) { + drupal_set_header("ETag: " .$etag); + } + // Return 304 not modified if either last modified or etag match. + if ($last_modified == $if_modified_since || $etag == $if_none_match) { + drupal_set_header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified'); + return; + } + + // The following headers force validation of cache: + drupal_set_header("Expires: Sun, 19 Nov 1978 05:00:00 GMT"); + drupal_set_header("Cache-Control: must-revalidate"); + drupal_set_header('Content-Type: application/rss+xml; charset=utf-8'); + + // Read actual feed from file. + $file_name = DRUPAL_ROOT . '/' . drupal_get_path('module', 'aggregator') . '/aggregator_test_rss091.xml'; + $handle = fopen($file_name, 'r'); + $feed = fread($handle, filesize($file_name)); + fclose($handle); + + print $feed; +} diff --git a/modules/aggregator/aggregator_test_rss091.xml b/modules/aggregator/aggregator_test_rss091.xml new file mode 100644 index 00000000000..9576f7c164f --- /dev/null +++ b/modules/aggregator/aggregator_test_rss091.xml @@ -0,0 +1,30 @@ + + + + Example + http://example.com + Example updates + en-us + Copyright 2000, Example team. + editor@example.com + webmaster@example.com + + Example + http://example.com/images/druplicon.png + http://example.com + 88 + 100 + Example updates + + + Example turns one + http://example.com/example-turns-one + Example turns one. + + + Example turns two + http://example.com/example-turns-two + Example turns two. + + + \ No newline at end of file