/* ********************************************************************** **
** Copyright notice **
** **
** (c) 2005-2009 RSSOwl Development Team **
** http://www.rssowl.org/ **
** **
** All rights reserved **
** **
** This program and the accompanying materials are made available under **
** the terms of the Eclipse Public License v1.0 which accompanies this **
** distribution, and is available at: **
** http://www.rssowl.org/legal/epl-v10.html **
** **
** A copy is found in the file epl-v10.html and important notices to the **
** license from the team is found in the textfile LICENSE.txt distributed **
** in this package. **
** **
** This copyright notice MUST APPEAR in all copies of the file! **
** **
** Contributors: **
** RSSOwl Development Team - initial API and implementation **
** **
** ********************************************************************** */
package org.rssowl.core.tests.persist;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.rssowl.core.Owl;
import org.rssowl.core.internal.InternalOwl;
import org.rssowl.core.internal.persist.Feed;
import org.rssowl.core.internal.persist.service.DBHelper;
import org.rssowl.core.internal.persist.service.DBManager;
import org.rssowl.core.internal.persist.service.EntityIdsByEventType;
import org.rssowl.core.internal.persist.service.PersistenceServiceImpl;
import org.rssowl.core.interpreter.InterpreterException;
import org.rssowl.core.interpreter.ParserException;
import org.rssowl.core.persist.IAttachment;
import org.rssowl.core.persist.IBookMark;
import org.rssowl.core.persist.ICategory;
import org.rssowl.core.persist.IEntity;
import org.rssowl.core.persist.IFeed;
import org.rssowl.core.persist.IFolder;
import org.rssowl.core.persist.IImage;
import org.rssowl.core.persist.IModelFactory;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.INews.State;
import org.rssowl.core.persist.IPersistable;
import org.rssowl.core.persist.IPerson;
import org.rssowl.core.persist.ISource;
import org.rssowl.core.persist.dao.DynamicDAO;
import org.rssowl.core.persist.reference.FeedLinkReference;
import org.rssowl.core.tests.TestUtils.NullProgressLongOperationMonitor;
import org.rssowl.core.tests.model.DBManagerTest;
import org.rssowl.core.tests.model.LargeBlockSizeTest;
import org.rssowl.core.util.CoreUtils;
import org.rssowl.core.util.LongOperationMonitor;
import org.rssowl.ui.internal.util.ImportUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Date;
import java.util.List;
/**
* Tests that trigger lifecycle methods run as last tests to not interfer other
* tests.
*/
public class StartupShutdownTest extends LargeBlockSizeTest {
private IModelFactory fFactory;
/**
* @throws Exception
*/
@Before
public void setUp() throws Exception {
((PersistenceServiceImpl) Owl.getPersistenceService()).recreateSchemaForTests();
fFactory = Owl.getModelFactory();
}
/**
* @throws Exception
*/
@After
public void tearDown() throws Exception {
System.setProperty("rssowl.reindex", "false"); //Clear any set reindex marker
DBManager.getDefault().getReIndexFile().delete();
DBManager.getDefault().getDefragmentFile().delete();
DBManager.getDefault().getCleanUpIndexFile().delete();
}
/**
* Tests that uncommitted news are saved and loaded correctly in the presence
* of an emergency or normal shutdown.
*
* @throws Exception
*/
@Test
public void testSaveLoadEntitiesToBeIndexed() throws Exception {
EntityIdsByEventType entitiesToBeIndexed = DBHelper.getEntitiesToBeIndexedDAO().load();
assertEquals(0, entitiesToBeIndexed.size());
IFeed feed = fFactory.createFeed(null, new URI("http://www.feed.com/feed.xml"));
INews news1 = createNews(feed, "Foo", null, "http://www.news.com/news1.html", State.READ);
INews news2 = createNews(feed, " Bar", null, "http://www.news.com/news2.html", State.NEW);
DynamicDAO.save(feed);
entitiesToBeIndexed = DBHelper.getEntitiesToBeIndexedDAO().load();
assertEquals(2, entitiesToBeIndexed.size());
Owl.getPersistenceService().shutdown(true);
Owl.getPersistenceService().startup(new NullProgressLongOperationMonitor(), false, false);
entitiesToBeIndexed = DBHelper.getEntitiesToBeIndexedDAO().load();
assertEquals(2, entitiesToBeIndexed.size());
for (long id : entitiesToBeIndexed.getPersistedEntityIds().toArray()) {
assertTrue(id == news1.getId().longValue() || id == news2.getId().longValue());
}
Owl.getPersistenceService().shutdown(false);
Owl.getPersistenceService().startup(new NullProgressLongOperationMonitor(), false, false);
waitForIndexer();
entitiesToBeIndexed = DBHelper.getEntitiesToBeIndexedDAO().load();
assertEquals(0, entitiesToBeIndexed.size());
}
/**
* @throws Exception
*/
@Test
public void testCleanUpOnNextStartup() {
Owl.getPersistenceService().getModelSearch().cleanUpOnNextStartup();
assertTrue(DBManager.getDefault().getCleanUpIndexFile().exists());
DBManager.getDefault().getCleanUpIndexFile().delete();
}
/**
* @throws Exception
*/
@Test
public void testReIndexOnNextStartup() {
Owl.getPersistenceService().getModelSearch().reIndexOnNextStartup();
assertTrue(DBManager.getDefault().getReIndexFile().exists());
}
/**
* @throws Exception
*/
@Test
public void testRecreateEmptyProfile() {
IFeed feed = DynamicDAO.save(createFeed());
INews news = createNews(feed);
news.setState(INews.State.NEW);
news.setFlagged(true);
DynamicDAO.save(news);
IFolder folder = Owl.getModelFactory().createFolder(null, null, "Root");
IBookMark bookmark = Owl.getModelFactory().createBookMark(null, folder, new FeedLinkReference(feed.getLink()), "Bookmark");
DynamicDAO.save(bookmark);
assertNotNull(feed.toReference().resolve());
assertNotNull(news.toReference().resolve());
assertNotNull(folder.toReference().resolve());
assertNotNull(bookmark.toReference().resolve());
InternalOwl.getDefault().recreateProfile(false); //Creates a new, empty rssowl.db.restore
assertTrue(new File(DBManager.getDBRestoreFilePath()).exists());
InternalOwl.getDefault().startup(new LongOperationMonitor(new NullProgressMonitor()) {}, false, false); //Normal startup will pickup rssowl.db.restore
assertFalse(new File(DBManager.getDBRestoreFilePath()).exists());
assertNull(feed.toReference().resolve());
assertNull(news.toReference().resolve());
assertNull(folder.toReference().resolve());
assertNull(bookmark.toReference().resolve());
feed = DynamicDAO.save(createFeed());
news = createNews(feed);
news.setState(INews.State.NEW);
news.setFlagged(true);
DynamicDAO.save(news);
folder = Owl.getModelFactory().createFolder(null, null, "Root");
bookmark = Owl.getModelFactory().createBookMark(null, folder, new FeedLinkReference(feed.getLink()), "Bookmark");
DynamicDAO.save(bookmark);
assertNotNull(feed.toReference().resolve());
assertNotNull(news.toReference().resolve());
assertNotNull(folder.toReference().resolve());
assertNotNull(bookmark.toReference().resolve());
}
/**
* @throws Exception
*/
@Test
@Ignore
public void testRecreateOPMLProfile() throws IOException, InterpreterException, ParserException {
IFeed feed = DynamicDAO.save(createFeed());
INews news = createNews(feed);
news.setState(INews.State.NEW);
news.setFlagged(true);
DynamicDAO.save(news);
IFolder folder = Owl.getModelFactory().createFolder(null, null, "Root");
IBookMark bookmark = Owl.getModelFactory().createBookMark(null, folder, new FeedLinkReference(feed.getLink()), "Bookmark");
DynamicDAO.save(bookmark);
assertNotNull(feed.toReference().resolve());
assertNotNull(news.toReference().resolve());
assertNotNull(folder.toReference().resolve());
assertNotNull(bookmark.toReference().resolve());
InternalOwl.getDefault().recreateProfile(true);
assertTrue(new File(DBManager.getDBRestoreFilePath()).exists());
assertNull(feed.toReference().resolve());
assertNull(news.toReference().resolve());
assertNull(folder.toReference().resolve());
assertNull(bookmark.toReference().resolve());
File tmpFile = File.createTempFile("rssowlopml", "tmp");
if (!tmpFile.exists())
tmpFile.createNewFile();
tmpFile.deleteOnExit();
CoreUtils.copy(DBManagerTest.class.getResourceAsStream("/data/default_feeds.xml"), new FileOutputStream(tmpFile));
List<? extends IEntity> types = InternalOwl.getDefault().getInterpreter().importFrom(new FileInputStream(tmpFile));
ImportUtils.doImport(null, types, false);
assertTrue(DynamicDAO.loadAll(INews.class).isEmpty());
assertTrue(DynamicDAO.loadAll(IBookMark.class).size() > 100);
assertTrue(DynamicDAO.loadAll(IFolder.class).size() > 20);
}
/**
* @throws Exception
*/
@Test
public void testRestoreProfile() throws IOException {
File marker = DBManager.getLargeBlockSizeMarkerFile();
boolean markerExists = marker.exists();
IFeed feed = DynamicDAO.save(createFeed());
INews news = createNews(feed);
news.setState(INews.State.NEW);
news.setFlagged(true);
DynamicDAO.save(news);
IFolder folder = Owl.getModelFactory().createFolder(null, null, "Root");
IBookMark bookmark = Owl.getModelFactory().createBookMark(null, folder, new FeedLinkReference(feed.getLink()), "Bookmark");
DynamicDAO.save(bookmark);
assertNotNull(feed.toReference().resolve());
assertNotNull(news.toReference().resolve());
assertNotNull(folder.toReference().resolve());
assertNotNull(bookmark.toReference().resolve());
File tmpFile = File.createTempFile("rssowldb", "tmp");
if (!tmpFile.exists())
tmpFile.createNewFile();
tmpFile.deleteOnExit();
CoreUtils.copy(DBManagerTest.class.getResourceAsStream("/data/rssowl.db"), new FileOutputStream(tmpFile));
InternalOwl.getDefault().restoreProfile(tmpFile);
assertTrue(new File(DBManager.getDBRestoreFilePath()).exists());
if (markerExists)
assertFalse(marker.exists());
InternalOwl.getDefault().startup(new LongOperationMonitor(new NullProgressMonitor()) {}, true, false);
assertFalse(new File(DBManager.getDBRestoreFilePath()).exists());
assertTrue(DynamicDAO.loadAll(INews.class).isEmpty());
assertTrue(DynamicDAO.loadAll(IBookMark.class).size() > 100);
assertTrue(DynamicDAO.loadAll(IFolder.class).size() > 20);
if (markerExists && !marker.exists())
marker.createNewFile();
}
private INews createNews(IFeed feed, String title, String description, String link, INews.State state) throws URISyntaxException {
INews news = fFactory.createNews(null, feed, new Date(System.currentTimeMillis()));
news.setState(state);
news.setLink(new URI(link));
news.setTitle(title);
if (description != null)
news.setDescription(description);
return news;
}
/**
* @throws InterruptedException
*/
protected void waitForIndexer() throws InterruptedException {
Thread.sleep(500);
}
private INews createNews(IFeed feed) {
INews news = fFactory.createNews(null, feed, createDate());
IAttachment attachment = fFactory.createAttachment(null, news);
attachment.setLink(createURI("http://attachmenturi.com"));
ICategory category = fFactory.createCategory(null, news);
category.setName("Category name #1");
news.setAuthor(createPersonMary(news));
news.setBase(createURI("http://www.someuri.com"));
news.setComments("One comment");
news.setState(State.HIDDEN);
news.setDescription("News description");
fFactory.createGuid(news, "someGUIDvalue", null);
news.setLink(createURI("http://www.somelocation.com/feed.rss"));
news.setModifiedDate(createDate());
news.setProperty("property", "value");
news.setPublishDate(createDate());
ISource source = fFactory.createSource(news);
source.setLink(createURI("http://www.someuri.com"));
news.setSource(source);
news.setTitle("This is the news title");
news.setRating(70);
return news;
}
private Feed createFeed() {
return createFeed("http://www.rssowl.org/feed.rss");
}
private Feed createFeed(String link) {
Feed feed = (Feed) fFactory.createFeed(null, createURI(link));
feed.setTitle("feed title");
feed.setDescription("feed description");
feed.setHomepage(createURI("http://www.rssowl.org"));
feed.setAuthor(createPersonJohn(feed));
feed.setLanguage("English");
feed.setCopyright("This feed is copyrighted");
feed.setDocs(createURI("http://www.rssowl.org/documentation.html"));
feed.setGenerator("Manual");
feed.setImage(createImage(feed));
feed.setPublishDate(createDate());
feed.setLastBuildDate(createDate());
feed.setLastModifiedDate(createDate());
feed.setWebmaster("Webmaster");
feed.setTTL(60);
feed.setFormat("RSS");
feed.setProperty("feedProperty", "randomValue");
feed.setBase(createURI("http://www.baseuri.com/"));
return feed;
}
URI createURI(String uri) {
try {
return new URI(uri);
} catch (URISyntaxException e) {
// should not happen;
return null;
}
}
private IPerson createPersonJohn(IPersistable type) {
IPerson person = fFactory.createPerson(null, type);
person.setName("John");
person.setEmail(createURI("john@hotmail.com"));
person.setUri(createURI("http://mysite.hotmail.com"));
person.setProperty("property", "property_value");
return person;
}
private IPerson createPersonMary(IPersistable type) {
IPerson person = fFactory.createPerson(null, type);
person.setName("Mary");
person.setEmail(createURI("mary@hotmail.com"));
person.setUri(createURI("http://mary.hotmail.com"));
person.setProperty("test", "property");
return person;
}
@SuppressWarnings("unused")
private IPerson createPersonDan(IPersistable type) {
IPerson person = fFactory.createPerson(null, type);
person.setName("Dan");
person.setEmail(createURI("dan@yahoo.com"));
return person;
}
private Date createDate() {
return new Date();
}
private IImage createImage(IFeed feed) {
IImage image = fFactory.createImage(feed);
image.setHomepage(createURI("http://www.rssowl.org/image.png"));
return image;
}
}