/* ********************************************************************** **
** 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.service;
import static junit.framework.Assert.assertNotNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.junit.Before;
import org.junit.Test;
import org.rssowl.core.Owl;
import org.rssowl.core.internal.persist.Attachment;
import org.rssowl.core.internal.persist.BookMark;
import org.rssowl.core.internal.persist.Category;
import org.rssowl.core.internal.persist.Description;
import org.rssowl.core.internal.persist.Feed;
import org.rssowl.core.internal.persist.Folder;
import org.rssowl.core.internal.persist.Label;
import org.rssowl.core.internal.persist.News;
import org.rssowl.core.internal.persist.Person;
import org.rssowl.core.internal.persist.Preference;
import org.rssowl.core.internal.persist.SearchCondition;
import org.rssowl.core.internal.persist.SearchMark;
import org.rssowl.core.internal.persist.service.Counter;
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.persist.IBookMark;
import org.rssowl.core.persist.IConditionalGet;
import org.rssowl.core.persist.IEntity;
import org.rssowl.core.persist.IFeed;
import org.rssowl.core.persist.IFolder;
import org.rssowl.core.persist.IFolderChild;
import org.rssowl.core.persist.ILabel;
import org.rssowl.core.persist.IModelFactory;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.INewsBin;
import org.rssowl.core.persist.IPreference;
import org.rssowl.core.persist.ISearch;
import org.rssowl.core.persist.ISearchCondition;
import org.rssowl.core.persist.ISearchFilter;
import org.rssowl.core.persist.ISearchMark;
import org.rssowl.core.persist.NewsCounter;
import org.rssowl.core.persist.NewsCounterItem;
import org.rssowl.core.persist.SearchSpecifier;
import org.rssowl.core.persist.dao.DynamicDAO;
import org.rssowl.core.persist.dao.INewsCounterDAO;
import org.rssowl.core.persist.reference.FeedLinkReference;
import com.db4o.Db4o;
import com.db4o.ObjectContainer;
import com.db4o.query.Query;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
* Tests defragmentation of db.
*/
public class DefragmentTest {
private URI fPluginLocation;
private IModelFactory fFactory = Owl.getModelFactory();
/**
* @throws Exception
*/
@Before
public void setUp() throws Exception {
Owl.getPersistenceService().recreateSchema();
fPluginLocation = FileLocator.toFileURL(Platform.getBundle("org.rssowl.core.tests").getEntry("/")).toURI();
/* Label */
ILabel label1 = fFactory.createLabel(null, "Label 0");
ILabel label2 = fFactory.createLabel(null, "Label 1");
label2.setColor("255,0,0");
DynamicDAO.save(label1);
DynamicDAO.save(label2);
/* Feeds and News */
List<IFeed> feeds = saveFeeds();
IFeed feed = feeds.get(1);
INews news = feed.getNews().get(2);
news.addLabel(label1);
news.addLabel(label2);
DynamicDAO.save(news);
INews anotherNews = feeds.get(feeds.size() - 1).getNews().get(0);
anotherNews.addLabel(label1);
DynamicDAO.save(anotherNews);
/* Folder, Bookmark and Searchmark */
IFolder folder = fFactory.createFolder(null, null, "Folder");
folder.setProperty("key", "value");
folder.setProperty("value", "key");
IBookMark bm = fFactory.createBookMark(null, folder, new FeedLinkReference(feed.getLink()), "BookMark");
bm.setProperty("key", "value");
bm.setProperty("value", "key");
IFeed anotherFeed = fFactory.createFeed(null, URI.create("http://www.rssowl.org"));
INews news1 = fFactory.createNews(null, anotherFeed, new Date());
news1.setState(INews.State.NEW);
INews news2 = fFactory.createNews(null, anotherFeed, new Date());
news2.setState(INews.State.UNREAD);
INews news4 = fFactory.createNews(null, anotherFeed, new Date());
news4.setState(INews.State.READ);
news4.setFlagged(true);
INews news5 = fFactory.createNews(null, anotherFeed, new Date());
news5.setState(INews.State.READ);
news5.setFlagged(true);
INews news6 = fFactory.createNews(null, anotherFeed, new Date());
news6.setState(INews.State.READ);
news6.setFlagged(true);
INews news7 = fFactory.createNews(null, anotherFeed, new Date());
news7.setState(INews.State.HIDDEN);
DynamicDAO.save(anotherFeed);
bm = fFactory.createBookMark(null, folder, new FeedLinkReference(URI.create("http://www.rssowl.org")), "Other BookMark");
NewsCounter counter = DynamicDAO.getDAO(INewsCounterDAO.class).load();
NewsCounterItem item = new NewsCounterItem(1, 2, 3);
counter.put(bm.getFeedLinkReference().getLinkAsText(), item);
DynamicDAO.save(counter);
((BookMark) bm).setNewsCounter(counter);
ISearchMark sm = fFactory.createSearchMark(null, folder, "SM");
sm.setProperty("key", "value");
sm.setProperty("value", "key");
ISearchCondition sc1 = fFactory.createSearchCondition(fFactory.createSearchField(INews.TITLE, INews.class.getName()), SearchSpecifier.IS, "foobar");
ISearchCondition sc2 = fFactory.createSearchCondition(fFactory.createSearchField(IEntity.ALL_FIELDS, INews.class.getName()), SearchSpecifier.CONTAINS, "test");
ISearchCondition sc3 = fFactory.createSearchCondition(fFactory.createSearchField(INews.PUBLISH_DATE, INews.class.getName()), SearchSpecifier.IS, new Date());
sm.addSearchCondition(sc1);
sm.addSearchCondition(sc2);
sm.addSearchCondition(sc3);
/* News Bin with News */
INewsBin bin = fFactory.createNewsBin(null, folder, "NewsBin");
DynamicDAO.save(folder);
INews newsCopy = fFactory.createNews(news, bin);
DynamicDAO.save(newsCopy);
DynamicDAO.save(bin);
/* Preference */
Preference pref = new Preference("longs");
pref.putLongs(2, 3, 4);
DynamicDAO.save(pref);
pref = new Preference("strings");
pref.putStrings("foo", "bar");
DynamicDAO.save(pref);
pref = new Preference("booleans");
pref.putBooleans(false, true);
DynamicDAO.save(pref);
pref = new Preference("integers");
pref.putIntegers(5, 6, 7);
DynamicDAO.save(pref);
pref = new Preference("long");
pref.putLongs(5);
DynamicDAO.save(pref);
pref = new Preference("string");
pref.putStrings("foobar");
DynamicDAO.save(pref);
pref = new Preference("boolean");
pref.putBooleans(true);
DynamicDAO.save(pref);
pref = new Preference("integer");
pref.putIntegers(8);
DynamicDAO.save(pref);
/* ISearchFilter with ISearch */
ISearch search = fFactory.createSearch(null);
sc1 = fFactory.createSearchCondition(fFactory.createSearchField(INews.TITLE, INews.class.getName()), SearchSpecifier.IS, "foobar");
sc2 = fFactory.createSearchCondition(fFactory.createSearchField(IEntity.ALL_FIELDS, INews.class.getName()), SearchSpecifier.CONTAINS, "test");
sc3 = fFactory.createSearchCondition(fFactory.createSearchField(INews.PUBLISH_DATE, INews.class.getName()), SearchSpecifier.IS, new Date());
search.addSearchCondition(sc1);
search.addSearchCondition(sc2);
search.addSearchCondition(sc3);
ISearchFilter filter = fFactory.createSearchFilter(null, search, "filter");
filter.addAction(fFactory.createFilterAction("action1"));
filter.addAction(fFactory.createFilterAction("action2"));
DynamicDAO.save(filter);
IConditionalGet conditionalGet = fFactory.createConditionalGet("2008-10-12-1943", URI.create("http://www.rssowl.org"), "foobar");
DynamicDAO.save(conditionalGet);
conditionalGet = fFactory.createConditionalGet("2008-10-12-1943", URI.create("http://www.rssowl.de"), "foobar");
DynamicDAO.save(conditionalGet);
}
/**
* Tests defragment.
*/
@Test
@SuppressWarnings( { "unchecked", "null" })
public void testDefragment() {
String dbPath = DBManager.getDBFilePath();
File originDbFile = new File(dbPath + ".origin");
DBHelper.copyFileIO(new File(dbPath), originDbFile, new NullProgressMonitor());
File defragmentedDbFile = new File(dbPath + ".dest");
DBManager.copyDatabase(originDbFile, defragmentedDbFile, new NullProgressMonitor());
System.gc();
ObjectContainer db = Db4o.openFile(DBManager.createConfiguration(false), originDbFile.getAbsolutePath());
ObjectContainer defragmentedDb = Db4o.openFile(DBManager.createConfiguration(false), defragmentedDbFile.getAbsolutePath());
/* Assert Number of Entities */
List<IEntity> entities = db.query(IEntity.class);
assertEquals(entities.size(), defragmentedDb.query(IEntity.class).size());
for (IEntity entity : entities) {
Query query = defragmentedDb.query();
query.constrain(entity.getClass());
query.descend("fId").constrain(Long.valueOf(entity.getId())); //$NON-NLS-1$
List<?> result = query.execute();
assertEquals(1, result.size());
assertEquals(entity, result.get(0));
if (entity instanceof Attachment)
assertTrue(((Attachment) entity).isIdentical((Attachment) result.get(0)));
else if (entity instanceof BookMark)
assertTrue(((BookMark) entity).isIdentical((BookMark) result.get(0)));
else if (entity instanceof Category)
assertTrue(((Category) entity).isIdentical((Category) result.get(0)));
else if (entity instanceof Feed)
assertTrue(((Feed) entity).isIdentical((Feed) result.get(0)));
else if (entity instanceof Folder)
assertTrue(((Folder) entity).isIdentical((Folder) result.get(0)));
else if (entity instanceof Label)
assertTrue(((Label) entity).isIdentical((Label) result.get(0)));
else if (entity instanceof News)
assertTrue(((News) entity).isIdentical((News) result.get(0)));
else if (entity instanceof Person)
assertTrue(((Person) entity).isIdentical((Person) result.get(0)));
else if (entity instanceof SearchCondition)
assertTrue(((SearchCondition) entity).isIdentical((SearchCondition) result.get(0)));
else if (entity instanceof SearchMark)
assertTrue(((SearchMark) entity).isIdentical((SearchMark) result.get(0)));
}
/* Assert News */
List<INews> newsList = db.query(INews.class);
assertEquals(newsList.size(), defragmentedDb.query(INews.class).size());
for (INews news : newsList) {
Query query = defragmentedDb.query();
query.constrain(news.getClass());
query.descend("fId").constrain(Long.valueOf(news.getId())); //$NON-NLS-1$
List<INews> result = query.execute();
assertEquals(1, result.size());
assertEquals(news.getTitle(), result.get(0).getTitle());
}
/* Assert Description */
List<Description> descriptions = db.query(Description.class);
assertEquals(descriptions.size(), defragmentedDb.query(Description.class).size());
for (Description description : descriptions) {
Query query = defragmentedDb.query();
query.constrain(description.getClass());
query.descend("fNewsId").constrain(Long.valueOf(description.getNews().getId())); //$NON-NLS-1$
List<Description> result = query.execute();
assertEquals(1, result.size());
assertEquals(description.getValue(), result.get(0).getValue());
}
/* Assert News Bins */
List<INewsBin> newsBins = db.query(INewsBin.class);
assertEquals(newsBins.size(), defragmentedDb.query(INewsBin.class).size());
for (INewsBin newsBin : newsBins) {
Query query = defragmentedDb.query();
query.constrain(newsBin.getClass());
query.descend("fId").constrain(Long.valueOf(newsBin.getId())); //$NON-NLS-1$
List<INewsBin> result = query.execute();
assertEquals(1, result.size());
assertEquals(newsBin.getNews(), result.get(0).getNews());
}
/* Assert Folders, Bookmarks and Searchmarks */
List<IFolder> folders = db.query(IFolder.class);
assertEquals(folders.size(), defragmentedDb.query(IFolder.class).size());
for (IFolder folder : folders) {
Query query = defragmentedDb.query();
query.constrain(folder.getClass());
query.descend("fId").constrain(Long.valueOf(folder.getId())); //$NON-NLS-1$
List<IFolder> result = query.execute();
assertEquals(1, result.size());
IFolder otherFolder = result.get(0);
assertTrue(folder.getName().equals(otherFolder.getName()));
assertTrue(folder.getProperties().equals(otherFolder.getProperties()));
IBookMark bm = null;
ISearchMark sm = null;
List<IFolderChild> children = folder.getChildren();
for (IFolderChild child : children) {
if (child instanceof IBookMark)
bm = (IBookMark) child;
else if (child instanceof ISearchMark)
sm = (ISearchMark) child;
}
IBookMark otherBM = null;
ISearchMark otherSM = null;
List<IFolderChild> otherChildren = otherFolder.getChildren();
for (IFolderChild otherChild : otherChildren) {
if (otherChild instanceof IBookMark)
otherBM = (IBookMark) otherChild;
else if (otherChild instanceof ISearchMark)
otherSM = (ISearchMark) otherChild;
}
assertNotNull(bm);
assertNotNull(sm);
assertNotNull(otherBM);
assertNotNull(otherSM);
assertTrue(bm.getName().equals(otherBM.getName()));
assertTrue(bm.getProperties().equals(otherBM.getProperties()));
assertTrue(sm.getSearchConditions().size() == otherSM.getSearchConditions().size());
}
/* Assert Preference */
List<IPreference> preferences = db.query(IPreference.class);
assertEquals(preferences.size(), defragmentedDb.query(IPreference.class).size());
for (IPreference preference : preferences) {
Query query = defragmentedDb.query();
query.constrain(preference.getClass());
query.descend("fId").constrain(Long.valueOf(preference.getId())); //$NON-NLS-1$
List<IPreference> result = query.execute();
assertEquals(1, result.size());
IPreference otherPreference = result.get(0);
assertEquals(preference.getKey(), otherPreference.getKey());
if ("string".equals(preference.getKey()))
assertEquals(preference.getString(), otherPreference.getString());
if ("strings".equals(preference.getKey()))
assertTrue(Arrays.equals(preference.getStrings(), otherPreference.getStrings()));
if ("boolean".equals(preference.getKey()))
assertEquals(preference.getBoolean(), otherPreference.getBoolean());
if ("booleans".equals(preference.getKey()))
assertTrue(Arrays.equals(preference.getBooleans(), otherPreference.getBooleans()));
if ("integer".equals(preference.getKey()))
assertEquals(preference.getInteger(), otherPreference.getInteger());
if ("integers".equals(preference.getKey()))
assertTrue(Arrays.equals(preference.getIntegers(), otherPreference.getIntegers()));
if ("long".equals(preference.getKey()))
assertEquals(preference.getLong(), otherPreference.getLong());
if ("longs".equals(preference.getKey()))
assertTrue(Arrays.equals(preference.getLongs(), otherPreference.getLongs()));
}
/* Assert Label */
List<ILabel> labels = db.query(ILabel.class);
assertEquals(labels.size(), defragmentedDb.query(ILabel.class).size());
for (ILabel label : labels) {
Query query = defragmentedDb.query();
query.constrain(label.getClass());
query.descend("fId").constrain(Long.valueOf(label.getId())); //$NON-NLS-1$
List<INewsBin> result = query.execute();
assertEquals(1, result.size());
assertTrue(((Label) label).isIdentical((ILabel) result.get(0)));
}
/* Assert Counter */
assertEquals(db.query(Counter.class).get(0).getValue(), defragmentedDb.query(Counter.class).get(0).getValue());
/* Assert Search Filter */
List<ISearchFilter> filters = db.query(ISearchFilter.class);
assertEquals(filters.size(), defragmentedDb.query(ISearchFilter.class).size());
for (ISearchFilter filter : filters) {
Query query = defragmentedDb.query();
query.constrain(filter.getClass());
query.descend("fId").constrain(Long.valueOf(filter.getId())); //$NON-NLS-1$
List<INewsBin> result = query.execute();
assertEquals(1, result.size());
ISearchFilter otherFilter = (ISearchFilter) result.get(0);
assertTrue(filter.getName().equals(otherFilter.getName()));
assertEquals(filter.getActions().size(), otherFilter.getActions().size());
ISearch search = filter.getSearch();
ISearch otherSearch = otherFilter.getSearch();
assertEquals(search.getSearchConditions().size(), otherSearch.getSearchConditions().size());
}
/* Assert Conditional Get */
List<IConditionalGet> condGets = db.query(IConditionalGet.class);
assertEquals(condGets.size(), defragmentedDb.query(IConditionalGet.class).size());
for (IConditionalGet condGet : condGets) {
Query query = defragmentedDb.query();
query.constrain(condGet.getClass());
query.descend("fLink").constrain(condGet.getLink().toString()); //$NON-NLS-1$
List<IConditionalGet> result = query.execute();
assertEquals(1, result.size());
IConditionalGet otherCondGet = result.get(0);
assertEquals(condGet.getIfModifiedSince(), otherCondGet.getIfModifiedSince());
assertEquals(condGet.getIfNoneMatch(), otherCondGet.getIfNoneMatch());
}
/* Assert EntityIdsByEventType */
EntityIdsByEventType eventType = db.query(EntityIdsByEventType.class).get(0);
EntityIdsByEventType otherEventType = defragmentedDb.query(EntityIdsByEventType.class).get(0);
assertNotNull(eventType);
assertNotNull(otherEventType);
assertEquals(eventType, otherEventType);
/* Assert NewsCounter / NewsCounterItem */
NewsCounter newsCounter = db.query(NewsCounter.class).get(0);
db.activate(newsCounter, Integer.MAX_VALUE);
NewsCounter otherNewsCounter = defragmentedDb.query(NewsCounter.class).get(0);
defragmentedDb.activate(otherNewsCounter, Integer.MAX_VALUE);
assertNotNull(newsCounter);
assertNotNull(otherNewsCounter);
NewsCounterItem item = otherNewsCounter.get("http://www.rssowl.org");
assertEquals(1, item.getNewCounter());
assertEquals(2, item.getUnreadCounter());
assertEquals(3, item.getStickyCounter());
}
private List<IFeed> saveFeeds() throws Exception {
List<IFeed> feeds = new ArrayList<IFeed>();
for (int i = 1; i < 200; i++) {
URI feedLink = fPluginLocation.resolve("data/performance/" + i + ".xml").toURL().toURI();
IFeed feed = new Feed(feedLink);
InputStream inS = new BufferedInputStream(new FileInputStream(new File(feed.getLink())));
Owl.getInterpreter().interpret(inS, feed, null);
feeds.add(feed);
}
DynamicDAO.saveAll(feeds);
return feeds;
}
}