// BlogBridge -- RSS feed reader, manager, and web based service
// Copyright (C) 2002-2006 by R. Pito Salas
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software Foundation;
// either version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with this program;
// if not, write to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA
//
// Contact: R. Pito Salas
// mailto:pitosalas@users.sourceforge.net
// More information: about BlogBridge
// http://www.blogbridge.com
// http://sourceforge.net/projects/blogbridge
//
// $Id: TestDataFeed.java,v 1.27 2008/02/28 15:59:53 spyromus Exp $
//
package com.salas.bb.domain;
import com.salas.bb.utils.parser.Channel;
import com.salas.bb.utils.parser.Item;
import junit.framework.TestCase;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
/**
* This suite contains tests for <code>DataFeed</code> unit.
* It covers:
* <ul>
* <li>Initialization of properties upon construction.</li>
* <li>Storing of: initialization time, last polling time, number of retrievals,
* number of articles polled, purge limit, flags for
* marking articles as read when no keywords found and automatic discovery
* of links in new articles.</li>
* <li>Getting and setting the list of read articles' keys.</li>
* <li>Adding, inserting and removing articles.</li>
* </ul>
*/
public class TestDataFeed extends TestCase
{
private DataFeed feed;
protected void setUp()
throws Exception
{
feed = new DummyDataFeed();
}
// ---------------------------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------------------------
/**
* Tests initialization of properties after construction.
*/
public void testConstruction()
{
assertEquals("Wrong purge limit setting.",
NetworkFeed.PURGE_LIMIT_INHERITED, feed.getPurgeLimit());
assertEquals("Wrong purge limit setting.",
NetworkFeed.DEFAULT_PURGE_LIMIT, feed.getPurgeLimitCombined());
assertEquals("Wrong default init time.",
NetworkFeed.INIT_TIME_UNINITIALIZED, feed.getInitTime());
assertEquals("Wrong last poll time.",
NetworkFeed.DEFAULT_LAST_POLL_TIME, feed.getLastPollTime());
assertEquals("Wrong last update time.",
NetworkFeed.DEFAULT_LAST_UPDATE_SERVER_TIME, feed.getLastUpdateServerTime());
assertEquals("Wrong total polled articles counter.",
NetworkFeed.DEFAULT_TOTAL_POLLED_ARTICLES, feed.getTotalPolledArticles());
assertEquals("Wrong number of retrievals.",
NetworkFeed.DEFAULT_RETRIEVALS, feed.getRetrievals());
}
/**
* Tests saving initialization time.
*/
public void testGetSetInitTime()
{
assertEquals("Wrong default init time.",
NetworkFeed.INIT_TIME_UNINITIALIZED, feed.getInitTime());
feed.setInitTime(1);
assertEquals("Wrong init time.", 1, feed.getInitTime());
}
/**
* Tests reporting initialization state. The feed is initialized when it's initialization
* time is set.
*/
public void testInitialized()
{
assertFalse("Feed should not be initialized.", feed.isInitialized());
feed.setInitTime(1);
assertTrue("Feed should be initialized.", feed.isInitialized());
}
/**
* Tests saving time of last poll.
*/
public void testGetSetLastPollTime()
{
assertEquals("Wrong last poll time.",
NetworkFeed.DEFAULT_LAST_POLL_TIME, feed.getLastPollTime());
feed.setLastPollTime(1);
assertEquals("Wrong last poll time.", 1, feed.getLastPollTime());
}
/**
* Tests saving the counter of retrievals.
*/
public void testGetSetRetrievals()
{
assertEquals("Wrong number of retrievals.",
NetworkFeed.DEFAULT_RETRIEVALS, feed.getRetrievals());
feed.setRetrievals(1);
assertEquals("Wrong number of retrievals.", 1, feed.getRetrievals());
}
/**
* Tests saving the counter of polled articles.
*/
public void testGetSetTotalPolledArticles()
{
assertEquals("Wrong total polled articles counter.",
NetworkFeed.DEFAULT_TOTAL_POLLED_ARTICLES, feed.getTotalPolledArticles());
feed.setTotalPolledArticles(10);
assertEquals("Wrong total polled articles counter.", 10, feed.getTotalPolledArticles());
}
/**
* Tests returning the list of keys of read articles.
* Feed is initialized.
*/
public void testGetReadArticlesKeysInitialized()
{
StandardArticle art1 = article(1);
art1.setRead(false);
feed.appendArticle(art1);
StandardArticle art2 = article(2);
art2.setRead(false);
feed.appendArticle(art2);
// Make feed to be initialized
feed.setInitTime(1);
String keys;
// Nothing marked as read
keys = feed.getReadArticlesKeys();
assertEquals("Should be no keys.", "", keys);
// Situation 1: there's read article present
art1.setRead(true);
keys = feed.getReadArticlesKeys();
assertEquals("Keys should have single key of read article.",
art1.getSimpleMatchKey(), keys);
// Situation 2: there are two read articles present
art2.setRead(true);
keys = feed.getReadArticlesKeys();
assertEquals("Keys should have single key of read article.",
art1.getSimpleMatchKey() + "," + art2.getSimpleMatchKey(), keys);
// Situation 3: Feed is empty
feed = new DummyNetworkFeed();
keys = feed.getReadArticlesKeys();
assertEquals("Should be no keys.", "", keys);
}
/**
* Tests returning the list of keys of read articles.
* Feed is not initialized
*/
public void testGetReadArticlesKeys()
{
StandardArticle art1 = article(1);
art1.setRead(false);
feed.appendArticle(art1);
StandardArticle art2 = article(2);
art2.setRead(false);
feed.appendArticle(art2);
String keys;
// Nothing marked as read
keys = feed.getReadArticlesKeys();
assertEquals("Should be no keys.", "", keys);
feed.setReadArticlesKeys("12345678,87654321");
keys = feed.getReadArticlesKeys();
assertEquals("Keys should be returned as is.", "12345678,87654321", keys);
}
/**
* Tests setting the list of keys of read articles. The articles which are
* currently in the feed and have the keys mentioned in the list should be
* marked as read immediately. Also the list of keys should be recorded.
*/
public void testSetReadArticlesKeys()
{
StandardArticle art1 = article(1);
art1.setRead(false);
feed.appendArticle(art1);
StandardArticle art2 = article(2);
art2.setRead(false);
feed.appendArticle(art2);
// Set the key of the first article as read
String keys = art1.getSimpleMatchKey();
feed.setReadArticlesKeys(keys);
assertTrue("Should be marked as read.", art1.isRead());
}
/**
* Tests the clearing of list of read articles keys.
*/
public void testSetReadArticlesKeysClear()
{
String keys;
feed.setReadArticlesKeys("12345678,87654321");
keys = feed.getReadArticlesKeys();
assertEquals("Keys should be returned as is.", "12345678,87654321", keys);
feed.setReadArticlesKeys(null);
keys = feed.getReadArticlesKeys();
assertEquals("Should be no keys.", "", keys);
}
/**
* Tests inheritance of the flag.
*/
public void testGetSetAutoFeedsDiscoveryInheritance()
{
assertEquals("Wrong default setting.", false, feed.isAutoFeedsDiscovery());
IGuide guide = new StandardGuide();
feed.addParentGuide(guide);
guide.setAutoFeedsDiscovery(true);
assertEquals("Wrong setting.", true, feed.isAutoFeedsDiscovery());
guide.setAutoFeedsDiscovery(false);
assertEquals("Wrong setting.", false, feed.isAutoFeedsDiscovery());
}
/**
* Tests saving of the purge limit property.
*/
public void testGetSetPurgeLimit()
{
assertEquals("Wrong purge limit setting.",
NetworkFeed.PURGE_LIMIT_INHERITED, feed.getPurgeLimit());
feed.setPurgeLimit(1);
assertEquals("Wrong purge limit setting.", 1, feed.getPurgeLimit());
}
/**
* Tests appending the article to the tail of feed.
*/
public void testAppendArticle()
{
feed = new DummyNetworkFeed();
assertEquals("Shoud be no articles.", 0, feed.getArticlesCount());
StandardArticle art1 = article(1);
StandardArticle art2 = article(2);
feed.appendArticle(art1);
assertEquals("Wrong article number.", 1, feed.getArticlesCount());
assertTrue("Wrong article added.", art1 == feed.getArticleAt(0));
assertTrue("Wrong feed.", feed == art1.getFeed());
feed.appendArticle(art2);
assertEquals("Wrong article number.", 2, feed.getArticlesCount());
assertTrue("Wrong article added.", art2 == feed.getArticleAt(1));
}
/**
* Tests appending duplicate article to the tail of feed.
*/
public void testAppendArticleDuplicate()
{
feed = new DummyNetworkFeed();
assertEquals("Shoud be no articles.", 0, feed.getArticlesCount());
StandardArticle art1 = new StandardArticle("");
feed.appendArticle(art1);
assertEquals("Wrong article number.", 1, feed.getArticlesCount());
try
{
feed.appendArticle(art1);
fail("The article is already in the feed. ISE is expected.");
} catch (IllegalStateException e)
{
// Expected
}
}
/**
* Tests appending articles with the same Link-Title-Pubdates.
*/
public void testAppendWikiArticlesDuplicate()
{
// wiki feed
feed = new DummyNetworkFeed();
feed.setHandlingType(FeedHandlingType.LINK_TITLE_PUBDATE);
Date today = new Date();
StandardArticle art1 = article("1", "http://localhost/1", today);
StandardArticle art2 = article("1", "http://localhost/1", today);
feed.appendArticle(art1);
assertEquals("Should add article", 1, feed.getArticlesCount());
feed.appendArticle(art2);
assertEquals("Should not add duplicate", 1, feed.getArticlesCount());
}
/**
* Tests appending articles with the same Link-Title but different Pubdates.
*/
public void testAppendWikiArticlesNonDuplicate()
{
// wiki feed
feed = new DummyNetworkFeed();
feed.setHandlingType(FeedHandlingType.LINK_TITLE_PUBDATE);
Date today = new Date();
Date yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000);
StandardArticle art1 = article("1", "http://localhost/1", yesterday);
StandardArticle art2 = article("1", "http://localhost/1", today);
feed.appendArticle(art1);
assertEquals("Should add article", 1, feed.getArticlesCount());
feed.appendArticle(art2);
assertEquals("Should add non-duplicate", 2, feed.getArticlesCount());
}
/**
* Tests handling of addition of NULL.
*/
public void testAppendArticleNull()
{
try
{
feed.appendArticle(null);
fail("NPE is expected.");
} catch (NullPointerException e)
{
// Expected
}
}
/**
* Tests inserting the article to the tail of feed.
*/
public void testInsertArticle()
{
feed = new DummyNetworkFeed();
assertEquals("Shoud be no articles.", 0, feed.getArticlesCount());
StandardArticle art1 = article(1);
StandardArticle art2 = article(2);
feed.insertArticle(0, art1);
assertEquals("Wrong article number.", 1, feed.getArticlesCount());
assertTrue("Wrong article added.", art1 == feed.getArticleAt(0));
feed.insertArticle(0, art2);
assertEquals("Wrong article number.", 2, feed.getArticlesCount());
assertTrue("Wrong article added.", art2 == feed.getArticleAt(0));
}
/**
* Tests appending duplicate article to the tail of feed.
*/
public void testInsertArticleDuplicate()
{
feed = new DummyNetworkFeed();
assertEquals("Shoud be no articles.", 0, feed.getArticlesCount());
StandardArticle art1 = new StandardArticle("");
feed.insertArticle(0, art1);
assertEquals("Wrong article number.", 1, feed.getArticlesCount());
try
{
feed.insertArticle(0, art1);
fail("The article is already in the feed. ISE is expected.");
} catch (IllegalStateException e)
{
// Expected
}
}
/**
* Tests handling of insertion of NULL.
*/
public void testInsertArticleNull()
{
try
{
feed.insertArticle(0, null);
fail("NPE is expected.");
} catch (NullPointerException e)
{
// Expected
}
}
/**
* Tests firing IOB exection when inserting article to some missing position.
*/
public void testInsertArticleAIOB()
{
feed = new DummyNetworkFeed();
assertEquals("Shoud be no articles.", 0, feed.getArticlesCount());
try
{
feed.insertArticle(1, new StandardArticle(""));
fail("IOB expected.");
} catch (IndexOutOfBoundsException e)
{
// Expected
}
}
/**
* Tests removing article from feed.
*/
public void testRemoveArticle()
{
feed = new DummyNetworkFeed();
assertEquals("Shoud be no articles.", 0, feed.getArticlesCount());
StandardArticle art1 = new StandardArticle("");
feed.insertArticle(0, art1);
assertTrue("Should report successful removal.", feed.removeArticle(art1));
assertEquals("Shoud be no articles.", 0, feed.getArticlesCount());
}
/**
* Tests duplicate removing of articles.
*/
public void testRemoveArticleDuplicate()
{
feed = new DummyNetworkFeed();
assertEquals("Shoud be no articles.", 0, feed.getArticlesCount());
StandardArticle art1 = new StandardArticle("");
feed.insertArticle(0, art1);
assertTrue("Should report successful removal.", feed.removeArticle(art1));
assertFalse("Shouldn't report successful removal.", feed.removeArticle(art1));
}
/**
* Tests handling of removing NULL-articles.
*/
public void testRemoveArticleNull()
{
try
{
feed.removeArticle(null);
fail("NPE is expected.");
} catch (NullPointerException e)
{
// Expected
}
}
/**
* Tests that articles added are being marked as read automatically if their
* keys are in the list of read articles' keys.
*/
public void testAutoReadOnAdding()
{
String keys;
feed = new DummyNetworkFeed();
StandardArticle art1 = article(1);
StandardArticle art2 = article(2);
keys = art1.getSimpleMatchKey();
feed.setReadArticlesKeys(keys);
feed.appendArticle(art1);
assertTrue("Should be marked as read.", art1.isRead());
assertEquals("Wrong unread count.", 0, feed.getUnreadArticlesCount());
feed.appendArticle(art2);
assertFalse("Should not be marked as read.", art2.isRead());
assertEquals("Wrong unread count.", 1, feed.getUnreadArticlesCount());
}
/**
* Tests getting format of the feed from its handle.
*/
public void testGetFormat()
{
assertNull("Format is not known.", feed.getFormat());
feed.setFormat("A");
assertEquals("Format is known.", "A", feed.getFormat());
}
/**
* Tests getting language of the feed from its handle.
*/
public void testGetLanguage()
{
assertNull("Language is not known.", feed.getLanguage());
feed.setLanguage("A");
assertEquals("Language is known.", "A", feed.getLanguage());
}
/**
* Tests reporting of updatable status by feed when it's invalid.
*/
public void testIsUpdatableInvalid()
{
feed.setInvalidnessReason(null);
feed.setID(1);
assertTrue("Feed is valid. It can be updatable.", feed.isUpdatable(false));
assertTrue("Feed is valid. It can be updatable.", feed.isUpdatable(true));
feed.setInvalidnessReason(null);
feed.setID(-1);
assertFalse("Feed isn't persisted. It cannot be updatable.", feed.isUpdatable(false, true));
assertFalse("Feed isn't persisted. It cannot be updatable.", feed.isUpdatable(true, true));
feed.setInvalidnessReason("A");
feed.setID(1);
assertFalse("Feed is invalid. It cannot be updatable.", feed.isUpdatable(false));
assertTrue("Feed is invalid, but questioned manually. It can be updatable.",
feed.isUpdatable(true));
feed.setInvalidnessReason("A");
feed.setID(-1);
assertFalse("Feed isn't persisted. It cannot be updatable.", feed.isUpdatable(false, true));
assertFalse("Feed isn't persisted. It cannot be updatable.", feed.isUpdatable(true, true));
}
/**
* Tests getting and setting update period and inheritance of the values.
*/
public void testGetSetUpdatePeriod()
{
feed.setUpdatePeriod(1);
assertEquals("Wrong period.", 1, feed.getUpdatePeriod());
feed.setUpdatePeriod(DataFeed.UPDATE_PERIOD_INHERITED);
assertEquals("Wrong period.", DataFeed.getGlobalUpdatePeriod(),
feed.getUpdatePeriodCombined());
}
/**
* Tests that the feed is reported to be not updatable if it's not time yet.
*/
public void testIsUpdatableNotTime()
{
// Setting the last update time to a second ago
long base = System.currentTimeMillis();
feed.setLastPollTime(base - 1000);
feed.setID(1);
// Setting five seconds period -- not time
feed.setUpdatePeriod(5000);
assertFalse("Too early for updates.", feed.isUpdatable(false));
assertTrue("Direct updates are allowed at any moment.", feed.isUpdatable(true));
// Setting half second period -- time has come
feed.setUpdatePeriod(500);
assertTrue("Time of updates has come.", feed.isUpdatable(false));
assertTrue("Direct updates are allowed at any moment.", feed.isUpdatable(true));
}
/** Tests manual-mode updates reporting. */
public void testIsUpdatableManual()
{
// Setting the last update time to yesterday
long base = System.currentTimeMillis();
feed.setLastPollTime(base - 24*60*60*1000);
feed.setID(1);
// Setting manual period
feed.setUpdatePeriod(0);
assertFalse("In manual mode, can't be auto-updated.", feed.isUpdatable(false));
assertTrue("Direct updates are allowed at any moment.", feed.isUpdatable(true));
}
/**
* Tests updating the feed data from parsed channel object.
*/
public void testUpdateFeed()
{
Channel channel = new Channel();
// The parsed channel has information about format and language,
// the feed we have -- has not. The information should be moved.
channel.setFormat("A");
channel.setLanguage("B");
feed.updateFeed(channel);
assertEquals("Wrong format.", "A", feed.getFormat());
assertEquals("Wrong language.", "B", feed.getLanguage());
// The parsed channel has no information about format and language,
// the feed we already have -- has. There should be no updates.
channel.setFormat(null);
channel.setLanguage(null);
feed.updateFeed(channel);
assertEquals("Wrong format.", "A", feed.getFormat());
assertEquals("Wrong language.", "B", feed.getLanguage());
}
/**
* Tests updating the articles list from parsed empty channel object.
*/
public void testUpdateArticlesEmpty()
{
// Channel has no articles
feed.updateArticles(new StandardArticle[0]);
assertEquals("Wrong number of articles.", 0, feed.getArticlesCount());
}
/**
* Tests updating the articles list from parsed channel object.
*/
public void testUpdateArticles()
{
StandardArticle[] incArticles = {article(1)};
feed.updateArticles(incArticles);
assertEquals("Wrong number of articles.", 1, feed.getArticlesCount());
// Continued updates should not add the same item
feed.updateArticles(incArticles);
assertEquals("Wrong number of articles.", 1, feed.getArticlesCount());
}
/**
* Tests the updates with detection of existing articles.
*/
public void testUpdateArticlesOld()
{
// First update -- single item
StandardArticle[] incArticles1 = new StandardArticle[]
{
article(2)
};
feed.updateArticles(incArticles1);
assertEquals("Wrong number of articles.", 1, feed.getArticlesCount());
assertEquals("Wrong article added.", "2", feed.getArticleAt(0).getHtmlText());
// Second update -- one new item and one old
StandardArticle[] incArticles2 = new StandardArticle[]
{
article(1), article(2), article(3)
};
feed.updateArticles(incArticles2);
assertEquals("Wrong number of articles.", 3, feed.getArticlesCount());
assertEquals("Wrong article added.", "3", feed.getArticleAt(0).getHtmlText());
assertEquals("Wrong article added.", "1", feed.getArticleAt(1).getHtmlText());
assertEquals("Wrong article added.", "2", feed.getArticleAt(2).getHtmlText());
}
/**
* Tests the scenario when there are more articles in the parsed channel then
* it's allowed by local limits. In this case the older articles should be skipped.
*/
public void testUpdateArticlesGreaterThanLimit()
{
// Configure incoming articles
StandardArticle[] incArticles = new StandardArticle[]
{
article(1), article(2), article(3)
};
feed.setPurgeLimit(2);
// Channel has 3 articles, the limit is 2
feed.updateArticles(incArticles);
assertEquals("Wrong number of articles.", 2, feed.getArticlesCount());
assertEquals("Wrong article added.", "2", feed.getArticleAt(0).getHtmlText());
assertEquals("Wrong article added.", "1", feed.getArticleAt(1).getHtmlText());
}
/**
* Tests the scenario when the feed contains several articles "from the future" in
* the top of the articles list. Normally, it will prevent to load the articles
* following them because they will be treated as "old" because the seen article
* (the one with future date) is on top of them. To avoid this behaviour it's proposed
* to continue reading channel after the future article has been seen.
*/
public void testUpdateArticlesFromFuture()
{
// Configure incoming articles
StandardArticle art1 = article(1);
StandardArticle art2 = article(2);
StandardArticle art3 = article(3);
// Set future date to the first article
GregorianCalendar cal = new GregorianCalendar();
cal.roll(Calendar.YEAR, 1);
Date futureDate = cal.getTime();
art1.setPublicationDate(futureDate);
// Add the "future" article during the first update
feed.updateArticles(new StandardArticle[] { art1 });
assertEquals("Wrong number of articles.", 1, feed.getArticlesCount());
// Now add more articles to the channel and run another update
feed.updateArticles(new StandardArticle[] { art1, art2, art3 });
assertEquals("Wrong number of articles.", 3, feed.getArticlesCount());
assertEquals("Wrong order of articles.", "3", feed.getArticleAt(0).getHtmlText());
assertEquals("Wrong order of articles.", "2", feed.getArticleAt(1).getHtmlText());
assertEquals("Wrong order of articles.", "1", feed.getArticleAt(2).getHtmlText());
}
/**
* This test ensures that the above test {@link #testUpdateArticlesFromFuture()}
* doesn't break anything.
*/
public void testUpdateArticlesFromFutureDuplicate()
{
// Configure incoming articles
StandardArticle art1 = article(1);
StandardArticle art1_1 = article(1);
StandardArticle art2 = article(2);
StandardArticle art3 = article(3);
// Set future date to the first article
GregorianCalendar cal = new GregorianCalendar();
cal.roll(Calendar.YEAR, 1);
Date futureDate = cal.getTime();
art1.setPublicationDate(futureDate);
// Set the dates so that the art2 is newer than art3
art2.setPublicationDate(new Date(3));
art3.setPublicationDate(new Date(2));
// Add the "future" article during the first update
feed.updateArticles(new StandardArticle[] { art1, art1_1, art2, art3 });
assertEquals("Wrong number of articles.", 3, feed.getArticlesCount());
assertEquals("Wrong order of articles.", "3", feed.getArticleAt(0).getHtmlText());
assertEquals("Wrong order of articles.", "2", feed.getArticleAt(1).getHtmlText());
assertEquals("Wrong order of articles.", "1", feed.getArticleAt(2).getHtmlText());
}
/**
* There are several feeds with an advertisement article (or articles) in the head of
* the articles list. There are tests to ensure that the article "from the future" never
* stops the processing, but there are several registered occasions when the first
* article is from the far past or has no date at all, but still usually appears at
* the top. We have to deal with this situation gracefully as well.
*/
public void testUpdateArticlesAdvert()
{
// Configure incoming articles
StandardArticle artAdvert = article(1);
StandardArticle art2 = article(2);
StandardArticle art3 = article(3);
// We have a feed with advert at first
feed.updateArticles(new StandardArticle[] { artAdvert });
assertEquals("Wrong number of articles.", 1, feed.getArticlesCount());
assertEquals("Wrong article.", "1", feed.getArticleAt(0).getHtmlText());
// Then the item1 is added to the feed
feed.updateArticles(new StandardArticle[] { artAdvert, art2 });
assertEquals("Wrong number of articles.", 2, feed.getArticlesCount());
assertEquals("Wrong article.", "2", feed.getArticleAt(0).getHtmlText());
assertEquals("Wrong article.", "1", feed.getArticleAt(1).getHtmlText());
// And now the item2 is added in front the item1 but after the advert, like this:
// advert -> item2 -> item1
feed.updateArticles(new StandardArticle[] { artAdvert, art3, art2 });
assertEquals("Wrong number of articles.", 3, feed.getArticlesCount());
assertEquals("Wrong article.", "3", feed.getArticleAt(0).getHtmlText());
assertEquals("Wrong article.", "2", feed.getArticleAt(1).getHtmlText());
assertEquals("Wrong article.", "1", feed.getArticleAt(2).getHtmlText());
}
/**
* Tests updating sequence when NULL feed is returned from <code>fetchFeed</code>.
*/
public void testUpdateNull()
{
DummyDataFeed feed = new DummyDataFeed();
feed.setChannel(null);
feed.update();
assertTrue("Feed should update time and counters in any case.",
feed.getLastPollTime() > DataFeed.DEFAULT_LAST_POLL_TIME);
assertEquals("Time of initialization should change accordingly.",
feed.getLastPollTime(), feed.getInitTime());
assertEquals("Retrieval count should grow.", 1, feed.getRetrievals());
}
/**
* Tests normal update sequence with updates to times and retrieval counts.
*/
public void testUpdateNotNull()
{
Channel channel = new Channel();
channel.addItem(new Item("1"));
DummyDataFeed feed = new DummyDataFeed();
feed.setChannel(channel);
long base = System.currentTimeMillis();
feed.update();
long initTime = feed.getInitTime();
assertTrue("Time should be updated.", feed.getLastPollTime() >= base);
assertTrue("Time should be updated.", initTime >= base);
assertEquals("Wrong retrievals count.", 1, feed.getRetrievals());
assertEquals("Wrong total articles counter.", 1, feed.getTotalPolledArticles());
assertTrue("Update method wasn't called.", feed.isUpdateArticlesCalled());
assertTrue("Update method wasn't called.", feed.isUpdateFeedCalled());
// Another update
base = System.currentTimeMillis();
feed.update();
assertTrue("Time should be updated.", feed.getLastPollTime() >= base);
assertEquals("Time should not be updated.", initTime, feed.getInitTime());
assertEquals("Wrong retrievals count.", 2, feed.getRetrievals());
assertEquals("Wrong total articles counter.", 1, feed.getTotalPolledArticles());
assertTrue("Update method wasn't called.", feed.isUpdateArticlesCalled());
assertTrue("Update method wasn't called.", feed.isUpdateFeedCalled());
}
/**
* Tests work of cleaner.
*
* @throws Exception if something goes wrong.
*/
public void testClean() throws Exception
{
// There's nothing to clean
feed.clean();
assertEquals("Wrong number of articles.", 0, feed.getArticlesCount());
// Adding two articles one by one (two updates) while having limit of 1
// The second update should call cleaner and remove the last article
DummyDataFeed feed = new DummyDataFeed();
feed.setPurgeLimit(1);
Channel channel1 = new Channel();
channel1.addItem(new Item("1"));
// First update
feed.setChannel(channel1);
feed.update();
// A little pause to create a gap between items
Thread.sleep(100);
Channel channel2 = new Channel();
Item item = new Item("2");
channel2.addItem(item);
// Second update
feed.setChannel(channel2);
feed.update();
assertEquals("Wrong number of articles.", 1, feed.getArticlesCount());
assertEquals("Wrong article is left.", "2", feed.getArticleAt(0).getHtmlText());
}
/**
* Tests work of cleaner.
*/
public void testCleanPinned()
{
// There's nothing to clean
feed.clean();
assertEquals("Wrong number of articles.", 0, feed.getArticlesCount());
// Adding two articles one by one (two updates) while having limit of 1
// The second update should call cleaner but the first article should be
// removed because of a pin.
DummyDataFeed feed = new DummyDataFeed();
feed.setPurgeLimit(1);
DataFeed.setGlobalPurgeUnread(false);
Channel channel1 = new Channel();
channel1.addItem(new Item("1"));
// First update
feed.setChannel(channel1);
feed.update();
feed.getArticleAt(0).setPinned(true);
Channel channel2 = new Channel();
Item item = new Item("2");
channel2.addItem(item);
// Second update
feed.setChannel(channel2);
feed.update();
assertEquals("Wrong number of articles.", 2, feed.getArticlesCount());
}
/**
* Assume there are 6 articles: 3 pinned and 3 not pinned.
* When we set the purge limit to 3 (and we know that pinned articles aren't removed)
* the 3 not pinned articles should stay as otherwise there will be no new articles
* once the number of pinned articles reaches the purge limit.
*/
public void testCleanNotCountPinned()
{
// Create a sample feed
DirectFeed feed = new DirectFeed();
DirectFeed.setGlobalPurgeUnread(true);
feed.setPurgeLimit(Integer.MAX_VALUE);
// Generate articles and add them to the feed
// First 3 are pinned
for (int i = 0; i < 6; i++)
{
String txt = Integer.toString(i);
StandardArticle article = new StandardArticle(txt);
article.setRead(false);
article.setTitle(txt);
article.setPinned(i < 3);
feed.appendArticle(article);
}
// Set purge limit to 3 and see if articles stay
feed.setPurgeLimit(3);
assertEquals("3 unpinned articles should stay", 6, feed.getArticlesCount());
}
/**
* Tests removal of correct items.
*/
public void testComplexClean()
{
DummyDataFeed feed = new DummyDataFeed();
long time = System.currentTimeMillis();
IArticle article0 = articleWithTime(time);
IArticle article1 = articleWithTime(time + 1000);
IArticle article2 = articleWithTime(time + 2000);
IArticle article3 = articleWithTime(time + 3000);
IArticle articlem1 = articleWithTime(time - 1000);
IArticle articlem2 = articleWithTime(time - 2000);
IArticle articlem3 = articleWithTime(time - 3000);
feed.appendArticle(articlem3);
feed.appendArticle(articlem2);
feed.appendArticle(articlem1);
feed.appendArticle(article0);
feed.appendArticle(article1);
feed.appendArticle(article2);
feed.appendArticle(article3);
feed.setPurgeLimit(2);
assertEquals(2, feed.getArticlesCount());
assertTrue(article2 == feed.getArticleAt(0));
assertTrue(article3 == feed.getArticleAt(1));
}
/**
* Creates a simple test article with the title and text equal to the given index.
*
* @param index index.
*
* @return article object.
*/
private static StandardArticle article(long index)
{
String text = Long.toString(index);
StandardArticle article = new StandardArticle(text);
article.setTitle(text);
return article;
}
/**
* Creates an article and initializes it with the time given.
*
* @param time time of pubication.
*
* @return article.
*/
private static StandardArticle articleWithTime(long time)
{
StandardArticle article = article(time);
article.setPublicationDate(new Date(time));
return article;
}
/**
* Tests the case when <code>purgeUnread</code> is FALSE meaning that the
* feed should not remove unread articles during cleanup.
*/
public void testCleanNoPurgeUnread()
{
// Disable purgin unread globally
boolean globalPurgeUnead = DataFeed.isGlobalPurgeUnread();
DataFeed.setGlobalPurgeUnread(false);
try
{
// Set purge limit to 1 article
DummyDataFeed feed = new DummyDataFeed();
feed.setPurgeLimit(1);
// Create unread articles and add them to the feed
StandardArticle art1 = article(1);
art1.setRead(false);
feed.appendArticle(art1);
StandardArticle art2 = article(2);
art2.setRead(false);
feed.appendArticle(art2);
// Clean and check
feed.clean();
assertEquals("Unread articles should not be purged.", 2, feed.getArticlesCount());
} finally
{
DataFeed.setGlobalPurgeUnread(globalPurgeUnead);
}
}
/**
* Tests the case when <code>purgeUnread</code> is FALSE meaning that the
* feed should not remove unread articles during cleanup. There will be another article
* which is read. It should be removed.
*/
public void testCleanNoPurgeUnread2()
{
// Disable purgin unread globally
boolean globalPurgeUnead = DataFeed.isGlobalPurgeUnread();
DataFeed.setGlobalPurgeUnread(false);
try
{
// Set purge limit to 1 article
DummyDataFeed feed = new DummyDataFeed();
feed.setPurgeLimit(1);
// Create 2 unread articles and one read and add them to the feed
StandardArticle art1 = article(1);
art1.setRead(false);
feed.appendArticle(art1);
StandardArticle art2 = article(2);
art2.setRead(true);
feed.appendArticle(art2);
StandardArticle art3 = article(3);
art3.setRead(false);
feed.appendArticle(art3);
// Clean and check
feed.clean();
assertEquals("Unread articles should not be purged.", 2, feed.getArticlesCount());
assertTrue("Wrong article.", art1 == feed.getArticleAt(0));
assertTrue("Wrong article.", art3 == feed.getArticleAt(1));
} finally
{
DataFeed.setGlobalPurgeUnread(globalPurgeUnead);
}
}
/**
* Tests the case when <code>purgeUnread</code> is FALSE meaning that the
* feed should not remove unread articles during cleanup.
*
* Covers the case when there're two read articles, one unread and purge limit set to 1.
* Unread article should stay.
*/
public void testCleanNoPurgeUnread3()
{
// Disable purgin unread globally
boolean globalPurgeUnead = DataFeed.isGlobalPurgeUnread();
DataFeed.setGlobalPurgeUnread(false);
try
{
// Set purge limit to 1 article
DummyDataFeed feed = new DummyDataFeed();
feed.setPurgeLimit(1);
// Create 2 unread articles and one read and add them to the feed
StandardArticle art1 = article(1);
art1.setRead(true);
feed.appendArticle(art1);
StandardArticle art2 = article(2);
art2.setRead(false);
feed.appendArticle(art2);
StandardArticle art3 = article(3);
art3.setRead(true);
feed.appendArticle(art3);
// Clean and check
feed.clean();
assertEquals("Unread articles should not be purged.", 1, feed.getArticlesCount());
assertTrue("Wrong article.", art2 == feed.getArticleAt(0));
} finally
{
DataFeed.setGlobalPurgeUnread(globalPurgeUnead);
}
}
/**
* Tests the computation of number of articles for removal.
*/
public void testCalcArticlesRemove()
{
assertEquals("Nothing, because the total is 0.",
0, DataFeed.calcArticlesToRemove(0, 0, 0, 3, false));
assertEquals("Nothing, because the total is 0.",
0, DataFeed.calcArticlesToRemove(0, 0, 0, 3, true));
assertEquals("Only one article can be removed because the rest are unread.",
1, DataFeed.calcArticlesToRemove(5, 4, 0, 3, false));
assertEquals("2 articles, because only two are unread and it's below the limit.",
2, DataFeed.calcArticlesToRemove(5, 2, 0, 3, false));
assertEquals("Nothing can be removed as total equals the limit.",
0, DataFeed.calcArticlesToRemove(3, 3, 0, 3, false));
assertEquals("Nothing can be removed as total equals the limit.",
0, DataFeed.calcArticlesToRemove(3, 2, 0, 3, false));
assertEquals("2 articles, because removing unread is allowed.",
2, DataFeed.calcArticlesToRemove(5, 4, 0, 3, true));
assertEquals("2 articles, because removing unread is allowed.",
2, DataFeed.calcArticlesToRemove(5, 2, 0, 3, true));
assertEquals("Nothing can be removed as total equals the limit.",
0, DataFeed.calcArticlesToRemove(3, 3, 0, 3, true));
assertEquals("Nothing can be removed as total equals the limit.",
0, DataFeed.calcArticlesToRemove(3, 2, 0, 3, true));
// Pinned articles never count
assertEquals("Pinned articles never count",
0, DataFeed.calcArticlesToRemove(6, 0, 3, 3, true));
assertEquals("Pinned articles never count",
1, DataFeed.calcArticlesToRemove(6, 0, 2, 3, true));
}
/**
* Tests how the last update server time field is populated during updates.
*/
public void testSavingLastUpdateServerTime()
{
Channel chan = new Channel();
chan.setLastUpdateServerTime(-1);
chan.addItem(new Item("1"));
DummyDataFeed feed = new DummyDataFeed();
feed.setChannel(chan);
feed.update();
assertEquals("Wrong last update server time.", -1, feed.getLastUpdateServerTime());
chan.setLastUpdateServerTime(1);
chan.addItem(new Item("2"));
feed.update();
assertEquals("Wrong last update server time.", 1, feed.getLastUpdateServerTime());
}
/**
* BUG: When pinned articles were being set, read articles list was being reset.
*/
public void testSettingKeysSeparately()
{
String readKeys = "12345";
String pinnedKeys = "67890";
DummyDataFeed feed = new DummyDataFeed();
feed.setReadArticlesKeys(readKeys);
feed.setPinnedArticlesKeys(pinnedKeys);
assertEquals(readKeys, feed.getReadArticlesKeys());
assertEquals(pinnedKeys, feed.getPinnedArticlesKeys());
}
/** Article factory.
*
* @param title title.
* @param link link.
* @param date date.
*
* @return article
*/
private static StandardArticle article(String title, String link, Date date)
{
StandardArticle art = new StandardArticle("");
try
{
art.setLink(new URL(link));
art.setTitle(title);
art.setPublicationDate(date);
} catch (MalformedURLException e)
{
fail("Bad link: " + link);
}
return art;
}
}