Package org.rssowl.core.tests.performance

Source Code of org.rssowl.core.tests.performance.PerformanceTest

/*   **********************************************************************  **
**   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.performance;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.junit.Before;
import org.junit.Test;
import org.rssowl.core.Owl;
import org.rssowl.core.internal.InternalOwl;
import org.rssowl.core.internal.persist.BookMark;
import org.rssowl.core.internal.persist.Feed;
import org.rssowl.core.internal.persist.Folder;
import org.rssowl.core.internal.persist.News;
import org.rssowl.core.internal.persist.pref.DefaultPreferences;
import org.rssowl.core.persist.IAttachment;
import org.rssowl.core.persist.IBookMark;
import org.rssowl.core.persist.ICategory;
import org.rssowl.core.persist.ICloud;
import org.rssowl.core.persist.IEntity;
import org.rssowl.core.persist.IFeed;
import org.rssowl.core.persist.IFolder;
import org.rssowl.core.persist.IGuid;
import org.rssowl.core.persist.IImage;
import org.rssowl.core.persist.ILabel;
import org.rssowl.core.persist.IMark;
import org.rssowl.core.persist.IModelFactory;
import org.rssowl.core.persist.INews;
import org.rssowl.core.persist.IPersistable;
import org.rssowl.core.persist.IPerson;
import org.rssowl.core.persist.ISearch;
import org.rssowl.core.persist.ISearchCondition;
import org.rssowl.core.persist.ISearchField;
import org.rssowl.core.persist.ISearchFilter;
import org.rssowl.core.persist.ISearchMark;
import org.rssowl.core.persist.ISource;
import org.rssowl.core.persist.ITextInput;
import org.rssowl.core.persist.SearchSpecifier;
import org.rssowl.core.persist.INews.State;
import org.rssowl.core.persist.dao.DynamicDAO;
import org.rssowl.core.persist.dao.INewsDAO;
import org.rssowl.core.persist.pref.IPreferenceScope;
import org.rssowl.core.persist.reference.FeedLinkReference;
import org.rssowl.core.persist.reference.FeedReference;
import org.rssowl.core.persist.service.IModelSearch;
import org.rssowl.core.persist.service.PersistenceException;
import org.rssowl.core.tests.Activator;
import org.rssowl.core.tests.TestUtils;
import org.rssowl.core.util.ITask;
import org.rssowl.core.util.TaskAdapter;
import org.rssowl.ui.internal.Controller;
import org.rssowl.ui.internal.services.SavedSearchService;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
* @author bpasero
*/
public class PerformanceTest {

  /* Define the number of Feeds here (1 - 216) */
  private static final int FEEDS = 200;

  /* Number of Jobs per JobQueue */
  private static final int JOBS = 10;

  private URI fPluginLocation;
  private Controller fController;
  private IModelSearch fModelSearch;

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Before
  public void setUp() throws Exception {
    InternalOwl.PERF_TESTING = true;
    Owl.getPersistenceService().recreateSchema();
    fModelSearch = Owl.getPersistenceService().getModelSearch();
    fPluginLocation = FileLocator.toFileURL(Platform.getBundle("org.rssowl.core.tests").getEntry("/")).toURI();
    fController = Controller.getDefault();
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void realWorldReloadTestWithFilters() throws Exception {
    /*
     * We use 2 to simulate better how things happen. The queue for saving has a
     * single job and there are multiple jobs for loading the online feed and
     * interpreting. However, since the test infrastructure uses a single
     */
    int jobsCount = 2;
    File corpus1Folder = new File(fPluginLocation.resolve("data/performance/corpus_10-03-07"));
    File corpus2Folder = new File(fPluginLocation.resolve("data/performance/corpus_10-06-07"));
    File corpus3Folder = new File(fPluginLocation.resolve("data/performance/corpus_10-09-07"));
    File tmpFolder = new File(System.getProperty("java.io.tmpdir"));
    File feedFolder = new File(tmpFolder.getAbsolutePath(), "rssowlfeeds");
    feedFolder.mkdir();
    feedFolder.deleteOnExit();

    /* Copy Feeds of corpus_10-03-07 to temp location */
    copyFeedFilesToTempLocation(corpus1Folder, feedFolder);

    /* Create Filter */
    {
      IModelFactory factory = Owl.getModelFactory();
      ISearch search = factory.createSearch(null);
      search.setMatchAllConditions(false);
      ISearchField field = factory.createSearchField(IEntity.ALL_FIELDS, INews.class.getName());
      search.addSearchCondition(factory.createSearchCondition(field, SearchSpecifier.CONTAINS_ALL, "foo bar president"));

      field = factory.createSearchField(INews.AUTHOR, INews.class.getName());
      search.addSearchCondition(factory.createSearchCondition(field, SearchSpecifier.IS, "foobar"));

      field = factory.createSearchField(INews.TITLE, INews.class.getName());
      search.addSearchCondition(factory.createSearchCondition(field, SearchSpecifier.IS, "anything"));

      ISearchFilter filter = factory.createSearchFilter(null, search, "Filter 1");
      filter.setEnabled(true);
      filter.setOrder(0);

      filter.addAction(factory.createFilterAction("org.rssowl.core.StopFilterAction"));

      DynamicDAO.save(filter);
    }

    List<ITask> tasks = getRealWorldReloadTasks(feedFolder.getAbsolutePath());

    System.gc();
    /* Initial Reload */
    System.out.println("Reloading Real Word Feeds With Filters: " + FEEDS + " Feeds [Initial - " + jobsCount + " Jobs] took: " + TestUtils.executeAndWait(tasks, jobsCount) + "ms");

    /* Copy Feeds of corpus_10-06-07 to temp location */
    copyFeedFilesToTempLocation(corpus2Folder, feedFolder);
    System.gc();

    /* Second Reload */
    System.out.println("Reloading Real Word Feeds With Filters: " + FEEDS + " Feeds [Second - " + jobsCount + " Jobs] took: " + TestUtils.executeAndWait(tasks, jobsCount) + "ms");

    /* Copy Feeds of corpus_10-06-09 to temp location */
    copyFeedFilesToTempLocation(corpus3Folder, feedFolder);
    System.gc();

    /* Third Reload */
    System.out.println("Reloading Real Word Feeds With Filters: " + FEEDS + " Feeds [Third - " + jobsCount + " Jobs] took: " + TestUtils.executeAndWait(tasks, jobsCount) + "ms");
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void realWorldReloadTest() throws Exception {
    /*
     * We use 2 to simulate better how things happen. The queue for saving has a
     * single job and there are multiple jobs for loading the online feed and
     * interpreting. However, since the test infrastructure uses a single
     */
    int jobsCount = 2;
    File corpus1Folder = new File(fPluginLocation.resolve("data/performance/corpus_10-03-07"));
    File corpus2Folder = new File(fPluginLocation.resolve("data/performance/corpus_10-06-07"));
    File corpus3Folder = new File(fPluginLocation.resolve("data/performance/corpus_10-09-07"));
    File tmpFolder = new File(System.getProperty("java.io.tmpdir"));
    File feedFolder = new File(tmpFolder.getAbsolutePath(), "rssowlfeeds");
    feedFolder.mkdir();
    feedFolder.deleteOnExit();

    /* Copy Feeds of corpus_10-03-07 to temp location */
    copyFeedFilesToTempLocation(corpus1Folder, feedFolder);
    List<ITask> tasks = getRealWorldReloadTasks(feedFolder.getAbsolutePath());

    System.gc();
    /* Initial Reload */
    System.out.println("Reloading Real Word Feeds: " + FEEDS + " Feeds [Initial - " + jobsCount + " Jobs] took: " + TestUtils.executeAndWait(tasks, jobsCount) + "ms");

    /* Copy Feeds of corpus_10-06-07 to temp location */
    copyFeedFilesToTempLocation(corpus2Folder, feedFolder);
    System.gc();

    /* Second Reload */
    System.out.println("Reloading Real Word Feeds: " + FEEDS + " Feeds [Second - " + jobsCount + " Jobs] took: " + TestUtils.executeAndWait(tasks, jobsCount) + "ms");

    /* Copy Feeds of corpus_10-06-09 to temp location */
    copyFeedFilesToTempLocation(corpus3Folder, feedFolder);
    System.gc();

  /* Third Reload */
    System.out.println("Reloading Real Word Feeds: " + FEEDS + " Feeds [Third - " + jobsCount + " Jobs] took: " + TestUtils.executeAndWait(tasks, jobsCount) + "ms");
  }

  private void copyFeedFilesToTempLocation(File corpusFolder, File feedFolder) throws FileNotFoundException, IOException {
    File[] feedFiles = feedFolder.listFiles();
    for (File file : feedFiles) {
      file.delete();
    }

    FileFilter filter = new FileFilter() {
      public boolean accept(File pathname) {
       return pathname.getName().contains("zip");
      }
    };

    File zipFile = corpusFolder.listFiles(filter)[0];
    FileInputStream fis = new FileInputStream(zipFile);
    ZipInputStream zin = new ZipInputStream(new BufferedInputStream(fis));
    ZipEntry entry;
    while ((entry = zin.getNextEntry()) != null) {
      File outputFile = new File(feedFolder, entry.getName());
      outputFile.deleteOnExit();

      FileOutputStream outS = new FileOutputStream(outputFile);
      copy(zin, outS);
    }
  }

  private static void copy(ZipInputStream zis, OutputStream fos) {
    try {
      int count;
      final int BUFFER = 2048;
      byte data[] = new byte[BUFFER];

      BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER);
      while ((count = zis.read(data, 0, BUFFER)) != -1) {
        dest.write(data, 0, count);
      }

      dest.flush();
      dest.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  private List<ITask> getRealWorldReloadTasks(String feedDirectory) {
    List<ITask> tasks = new ArrayList<ITask>();

    /* Create Folder with all Bookmarks */
    IFolder rootFolder = new Folder(null, null, "Root");
    for (int i = 1; i < FEEDS + 1; i++) {
      try {
        File file = new File(feedDirectory, i + ".xml");
        if (!file.exists())
          continue;

        URI feedLink = file.toURI();

        IFeed feed = new Feed(feedLink);

        feed = DynamicDAO.save(feed);

        IBookMark bookmark = new BookMark(null, rootFolder, new FeedLinkReference(feed.getLink()), "Bookmark");
        IPreferenceScope entityScope = Owl.getPreferenceService().getEntityScope(bookmark);
        entityScope.putInteger(DefaultPreferences.DEL_NEWS_BY_COUNT_VALUE, 50);
        rootFolder.addMark(bookmark, null, false);
        DynamicDAO.save(rootFolder);
      } catch (Exception e) {
        Activator.getDefault().logError(e.getMessage(), e);
      }
    }

    /* Create Tasks */
    List<IMark> marks = rootFolder.getMarks();
    for (IMark mark : marks) {
      if (mark instanceof IBookMark) {
        final IBookMark bookmark = (IBookMark) mark;

        tasks.add(new TaskAdapter() {
          public IStatus run(IProgressMonitor monitor) {
            return fController.reload(bookmark, null, new NullProgressMonitor());
          }
        });
      }
    }

    return tasks;
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void savedSearchServiceTest() throws Exception {
    final List<Exception> ex = new ArrayList<Exception>();

    /* Cold-Start: Run Saved Search Service on 216 Feeds */
    List<ITask> tasks = getSavedSearchServiceTestTasks(ex);
    System.out.println("Running Saved Search Service on " + FEEDS + " Feeds [Cold - " + 1 + " Jobs] took: " + TestUtils.executeAndWait(tasks, 1) + "ms");

    /* Warm-Start: Run Saved Search Service on 216 Feeds */
    Owl.getPersistenceService().recreateSchema();
    tasks = getSavedSearchServiceTestTasks(ex);
    long l1 = TestUtils.executeAndWait(tasks, 1);

    Owl.getPersistenceService().recreateSchema();
    tasks = getSavedSearchServiceTestTasks(ex);
    long l2 = TestUtils.executeAndWait(tasks, 1);

    System.out.println("Running Saved Search Service on " + FEEDS + " Feeds [Warm - " + 1 + " Jobs] took: " + (l1 + l2) / 2 + "ms");

    if (ex.size() > 0)
      throw ex.get(0);
  }

  List<ITask> getSavedSearchServiceTestTasks(final List<Exception> ex) {
    List<ITask> tasks = new ArrayList<ITask>();

    /* Create Saved Searches */
    createSavedSearches();

    /* Save some Feeds first */
    saveFeedsHelper();

    final SavedSearchService smService = new SavedSearchService();

    tasks.add(new TaskAdapter() {
      public IStatus run(IProgressMonitor monitor) {
        try {
          smService.updateSavedSearches(DynamicDAO.loadAll(ISearchMark.class));
          smService.stopService();
        } catch (Exception e) {
          ex.add(e);
        }
        return Status.OK_STATUS;
      }
    });

    return tasks;
  }

  @SuppressWarnings("unused")
  private void createSavedSearches() {
    IFolder folder = Owl.getModelFactory().createFolder(null, null, "Default");
    IModelFactory factory = Owl.getModelFactory();

    /* Create Default SearchMarks */
    String newsEntityName = INews.class.getName();

    /* SearchCondition: New and Updated News */
    {
      ISearchMark mark = factory.createSearchMark(null, folder, "New and Updated News");

      ISearchField field1 = factory.createSearchField(INews.STATE, newsEntityName);
      factory.createSearchCondition(null, mark, field1, SearchSpecifier.IS, EnumSet.of(State.NEW));
    }

    /* SearchCondition: Recent News */
    {
      ISearchMark mark = factory.createSearchMark(null, folder, "Recent News");

      ISearchField field1 = factory.createSearchField(INews.AGE_IN_DAYS, newsEntityName);
      factory.createSearchCondition(null, mark, field1, SearchSpecifier.IS_LESS_THAN, 2);
    }

    /* SearchCondition: News with Attachments */
    {
      ISearchMark mark = factory.createSearchMark(null, folder, "News with Attachments");

      ISearchField field = factory.createSearchField(INews.HAS_ATTACHMENTS, newsEntityName);
      factory.createSearchCondition(null, mark, field, SearchSpecifier.IS, true);
    }

    /* SearchCondition: Sticky News */
    {
      ISearchMark mark = factory.createSearchMark(null, folder, "Sticky News");

      ISearchField field = factory.createSearchField(INews.IS_FLAGGED, newsEntityName);
      factory.createSearchCondition(null, mark, field, SearchSpecifier.IS, true);
    }

    /*
     * Condition : +(State IS *new* OR State is *unread* OR State IS *updated*)
     * AND +((Entire News contains "Foo") OR Author is "Benjamin Pasero")
     */
    {
      ISearchMark mark = factory.createSearchMark(null, folder, "Complex Search");

      ISearchField field1 = factory.createSearchField(INews.STATE, newsEntityName);
      ISearchCondition cond1 = factory.createSearchCondition(null, mark, field1, SearchSpecifier.IS, EnumSet.of(INews.State.NEW, State.UNREAD, State.UPDATED));

      ISearchField field4 = factory.createSearchField(IEntity.ALL_FIELDS, newsEntityName);
      ISearchCondition cond4 = factory.createSearchCondition(null, mark, field4, SearchSpecifier.CONTAINS, "Foo");

      ISearchField field5 = factory.createSearchField(INews.AUTHOR, newsEntityName);
      ISearchCondition cond5 = factory.createSearchCondition(null, mark, field5, SearchSpecifier.IS, "Benjamin Pasero");
    }

    /*
     * Condition : +(State IS *new* OR State is *unread* OR State IS *updated*)
     * AND (Entire News contains "Foo") AND (Author is "Benjamin Pasero")
     */
    {
      ISearchMark mark = factory.createSearchMark(null, folder, "Complex Search");

      ISearchField field1 = factory.createSearchField(INews.STATE, newsEntityName);
      ISearchCondition cond1 = factory.createSearchCondition(null, mark, field1, SearchSpecifier.IS, EnumSet.of(INews.State.NEW, State.UNREAD, State.UPDATED));

      ISearchField field4 = factory.createSearchField(IEntity.ALL_FIELDS, newsEntityName);
      ISearchCondition cond4 = factory.createSearchCondition(null, mark, field4, SearchSpecifier.CONTAINS, "Foo");

      ISearchField field5 = factory.createSearchField(INews.AUTHOR, newsEntityName);
      ISearchCondition cond5 = factory.createSearchCondition(null, mark, field5, SearchSpecifier.CONTAINS, "Benjamin Pasero");
    }

    /*
     * Condition : (Entire News contains "Foo") AND (Title contains "Bar") AND
     * (Author is not "Benjamin Pasero")
     */
    {
      ISearchMark mark = factory.createSearchMark(null, folder, "Complex Search");

      ISearchField field1 = factory.createSearchField(IEntity.ALL_FIELDS, newsEntityName);
      ISearchCondition cond1 = factory.createSearchCondition(null, mark, field1, SearchSpecifier.CONTAINS, "fafa");

      ISearchField field2 = factory.createSearchField(INews.TITLE, newsEntityName);
      ISearchCondition cond2 = factory.createSearchCondition(null, mark, field2, SearchSpecifier.CONTAINS, "Bar");

      ISearchField field3 = factory.createSearchField(INews.AUTHOR, newsEntityName);
      ISearchCondition cond3 = factory.createSearchCondition(null, mark, field3, SearchSpecifier.IS_NOT, "Benjamin Pasero");
    }

    /*
     * Condition : +(State IS *new* OR State is *unread* OR State IS *updated*)
     * AND (Category IS Windows) AND (Category IS Apple)
     */
    {
      ISearchMark mark = factory.createSearchMark(null, folder, "Complex Search");

      ISearchField field1 = factory.createSearchField(INews.STATE, newsEntityName);
      ISearchCondition cond1 = factory.createSearchCondition(null, mark, field1, SearchSpecifier.IS, EnumSet.of(INews.State.NEW, State.UNREAD, State.UPDATED));

      ISearchField field4 = factory.createSearchField(INews.CATEGORIES, newsEntityName);
      ISearchCondition cond4 = factory.createSearchCondition(null, mark, field4, SearchSpecifier.IS, "windows");

      ISearchField field5 = factory.createSearchField(INews.CATEGORIES, newsEntityName);
      ISearchCondition cond5 = factory.createSearchCondition(null, mark, field5, SearchSpecifier.IS, "apple");
    }

    /*
     * Condition : +(State IS *new* OR State is *unread* OR State IS *updated*)
     * AND (Category IS Windows) AND (Category IS Apple) AND (Category IS NOT
     * Slashdot)
     */
    {
      ISearchMark mark = factory.createSearchMark(null, folder, "Complex Search");

      ISearchField field1 = factory.createSearchField(INews.STATE, newsEntityName);
      ISearchCondition cond1 = factory.createSearchCondition(null, mark, field1, SearchSpecifier.IS, EnumSet.of(INews.State.NEW, State.UNREAD, State.UPDATED));

      ISearchField field4 = factory.createSearchField(INews.CATEGORIES, newsEntityName);
      ISearchCondition cond4 = factory.createSearchCondition(null, mark, field4, SearchSpecifier.IS, "windows");

      ISearchField field5 = factory.createSearchField(INews.CATEGORIES, newsEntityName);
      ISearchCondition cond5 = factory.createSearchCondition(null, mark, field5, SearchSpecifier.IS, "apple");

      ISearchField field6 = factory.createSearchField(INews.CATEGORIES, newsEntityName);
      factory.createSearchCondition(null, mark, field6, SearchSpecifier.IS_NOT, "slashdot");
    }

    /*
     * Condition : +(State IS *new* OR State is *unread* OR State IS *updated*)
     * AND (Category IS NOT Windows)
     */
    {
      ISearchMark mark = factory.createSearchMark(null, folder, "Complex Search");

      ISearchField field1 = factory.createSearchField(INews.STATE, newsEntityName);
      ISearchCondition cond1 = factory.createSearchCondition(null, mark, field1, SearchSpecifier.IS, EnumSet.of(INews.State.NEW, State.UNREAD, State.UPDATED));

      ISearchField field4 = factory.createSearchField(INews.CATEGORIES, newsEntityName);
      ISearchCondition cond4 = factory.createSearchCondition(null, mark, field4, SearchSpecifier.IS_NOT, "windows");
    }

    /*
     * Condition : +(State IS *new* OR State is *unread* OR State IS *updated*)
     * AND (Age is Less than 5 Days)
     */
    {
      ISearchMark mark = factory.createSearchMark(null, folder, "Complex Search");

      ISearchField field1 = factory.createSearchField(INews.STATE, newsEntityName);
      ISearchCondition cond1 = factory.createSearchCondition(null, mark, field1, SearchSpecifier.IS, EnumSet.of(INews.State.NEW, State.UNREAD, State.UPDATED));

      ISearchField field4 = factory.createSearchField(INews.AGE_IN_DAYS, newsEntityName);
      ISearchCondition cond4 = factory.createSearchCondition(null, mark, field4, SearchSpecifier.IS_LESS_THAN, 5);
    }

    /*
     * Condition 5: (State IS *new* OR State is *unread* OR State IS *updated*)
     * AND All_Fields CONTAINS foo
     */
    {
      ISearchMark mark = factory.createSearchMark(null, folder, "Complex Search");

      ISearchField field1 = factory.createSearchField(INews.STATE, newsEntityName);
      ISearchCondition cond1 = factory.createSearchCondition(null, mark, field1, SearchSpecifier.IS, EnumSet.of(INews.State.NEW, State.UNREAD, State.UPDATED));

      ISearchField field4 = factory.createSearchField(IEntity.ALL_FIELDS, newsEntityName);
      ISearchCondition cond4 = factory.createSearchCondition(null, mark, field4, SearchSpecifier.CONTAINS, "pasero");
    }

    DynamicDAO.save(folder);
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void saveAndIndexFeeds() throws Exception {
    final List<Exception> ex = new ArrayList<Exception>();

    /* Cold-Start: Save and Index 216 Feeds */
    List<ITask> tasks = getSaveAndIndexFeedsTasks(ex);
    System.out.println("Saving and Indexing " + FEEDS + " Feeds [Cold - " + 1 + " Jobs] took: " + TestUtils.executeAndWait(tasks, 1) + "ms");

    /* Warm-Start: Save and Index 216 Feeds */
    Owl.getPersistenceService().recreateSchema();
    tasks = getSaveAndIndexFeedsTasks(ex);
    long l1 = TestUtils.executeAndWait(tasks, 1);

    Owl.getPersistenceService().recreateSchema();
    tasks = getSaveAndIndexFeedsTasks(ex);
    long l2 = TestUtils.executeAndWait(tasks, 1);

    System.out.println("Saving and Indexing " + FEEDS + " Feeds [Warm - " + 1 + " Jobs] took: " + (l1 + l2) / 2 + "ms");

    /* Warm-Start: Save 216 Feeds with search disabled (to calculate plain index time) */
    Owl.getPersistenceService().recreateSchema();
    Owl.getPersistenceService().getModelSearch().shutdown(false);
    tasks = getSaveAndIndexFeedsTasks(ex);
    long l3 = TestUtils.executeAndWait(tasks, 1);

    Owl.getPersistenceService().getModelSearch().startup();
    Owl.getPersistenceService().recreateSchema();
    Owl.getPersistenceService().getModelSearch().shutdown(false);
    tasks = getSaveAndIndexFeedsTasks(ex);
    long l4 = TestUtils.executeAndWait(tasks, 1);

    /* Switch model search back on at the end */
    Owl.getPersistenceService().getModelSearch().startup();

    long indexL = (l1 + l2) / 2 - (l3 + l4) / 2;

    System.out.println("Indexing " + FEEDS + " Feeds [Warm - " + 1 + " Jobs] took: " + indexL + "ms\n");

    if (ex.size() > 0)
      throw ex.get(0);
  }

  private List<ITask> getSaveAndIndexFeedsTasks(final List<Exception> ex) {
    List<ITask> tasks = new ArrayList<ITask>();
    List<IFeed> feeds = interpretFeedsHelper();

    for (final IFeed feed : feeds) {
      tasks.add(new TaskAdapter() {
        public IStatus run(IProgressMonitor monitor) {
          try {
            DynamicDAO.save(feed);
          } catch (Exception e) {
            ex.add(e);
          }
          return Status.OK_STATUS;
        }
      });
    }

    return tasks;
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void searchNews() throws Exception {
    final List<Exception> ex = new ArrayList<Exception>();
    final int[] results = new int[] { 0 };
    final IModelFactory factory = Owl.getModelFactory();
    List<ITask> tasks = new ArrayList<ITask>();
    fModelSearch.startup();

    /* Save some Feeds first */
    saveFeedsHelper();

    /* Query 1: News is *new*, *unread*, *updated*, *read* */
    ITask task = new TaskAdapter() {
      public IStatus run(IProgressMonitor monitor) {
        List<ISearchCondition> conditions = new ArrayList<ISearchCondition>();

        ISearchField field1 = factory.createSearchField(INews.STATE, INews.class.getName());
        conditions.add(factory.createSearchCondition(field1, SearchSpecifier.IS, EnumSet.of(INews.State.NEW, State.UNREAD, State.UPDATED, State.READ)));

        results[0] = fModelSearch.searchNews(conditions, false).size();

        return Status.OK_STATUS;
      }
    };
    tasks.clear();
    tasks.add(task);
    long l1 = TestUtils.executeAndWait(tasks, 1);
    System.out.println("Searching [States (" + results[0] + " results, Occur.SHOULD, Cold)] in " + FEEDS + " Feeds took: " + l1 + "ms");

    /* Recreate */
    Owl.getPersistenceService().recreateSchema();
    saveFeedsHelper();

    /* Query 2: Entire News contains 'news' */
    task = new TaskAdapter() {
      public IStatus run(IProgressMonitor monitor) {
        List<ISearchCondition> conditions = new ArrayList<ISearchCondition>();

        ISearchField field1 = factory.createSearchField(IEntity.ALL_FIELDS, INews.class.getName());
        conditions.add(factory.createSearchCondition(field1, SearchSpecifier.CONTAINS, "news"));

        results[0] = fModelSearch.searchNews(conditions, false).size();

        return Status.OK_STATUS;
      }
    };
    tasks.clear();
    tasks.add(task);
    System.gc();
    long l2 = TestUtils.executeAndWait(tasks, 1);
    System.out.println("Searching [Entire News (" + results[0] + " results, Occur.SHOULD, Cold)] in " + FEEDS + " Feeds took: " + l2 + "ms");

    /* Recreate */
    Owl.getPersistenceService().recreateSchema();
    saveFeedsHelper();

    /*
     * Query 3: Title contains 'news' OR Author contains 's*' OR Category begins
     * with 'e'
     */
    task = new TaskAdapter() {
      public IStatus run(IProgressMonitor monitor) {
        List<ISearchCondition> conditions = new ArrayList<ISearchCondition>();

        ISearchField field1 = factory.createSearchField(INews.TITLE, INews.class.getName());
        conditions.add(factory.createSearchCondition(field1, SearchSpecifier.CONTAINS, "news"));

        ISearchField field2 = factory.createSearchField(INews.AUTHOR, INews.class.getName());
        conditions.add(factory.createSearchCondition(field2, SearchSpecifier.CONTAINS, "s*"));

        ISearchField field3 = factory.createSearchField(INews.CATEGORIES, INews.class.getName());
        conditions.add(factory.createSearchCondition(field3, SearchSpecifier.BEGINS_WITH, "e"));

        results[0] = fModelSearch.searchNews(conditions, false).size();

        return Status.OK_STATUS;
      }
    };
    tasks.clear();
    tasks.add(task);
    System.gc();
    long l3 = TestUtils.executeAndWait(tasks, 1);
    System.out.println("Searching [Title, Author, Categories (" + results[0] + " results, Occur.SHOULD, Cold)] in " + FEEDS + " Feeds took: " + l3 + "ms");

    /* Recreate */
    Owl.getPersistenceService().recreateSchema();
    saveFeedsHelper();

    /*
     * Query 4: Title contains 'news' AND Author contains 's*' AND Category
     * begins with 'e'
     */
    task = new TaskAdapter() {
      public IStatus run(IProgressMonitor monitor) {
        List<ISearchCondition> conditions = new ArrayList<ISearchCondition>();

        ISearchField field1 = factory.createSearchField(INews.TITLE, INews.class.getName());
        conditions.add(factory.createSearchCondition(field1, SearchSpecifier.CONTAINS, "news"));

        ISearchField field2 = factory.createSearchField(INews.AUTHOR, INews.class.getName());
        conditions.add(factory.createSearchCondition(field2, SearchSpecifier.CONTAINS, "s*"));

        ISearchField field3 = factory.createSearchField(INews.CATEGORIES, INews.class.getName());
        conditions.add(factory.createSearchCondition(field3, SearchSpecifier.BEGINS_WITH, "e"));

        results[0] = fModelSearch.searchNews(conditions, true).size();

        return Status.OK_STATUS;
      }
    };
    tasks.clear();
    tasks.add(task);
    System.gc();
    long l4 = TestUtils.executeAndWait(tasks, 1);
    System.out.println("Searching [Title, Author, Categories (" + results[0] + " results, Occur.MUST, Cold)] in " + FEEDS + " Feeds took: " + l4 + "ms");

    /* Recreate */
    Owl.getPersistenceService().recreateSchema();
    saveFeedsHelper();

    /* Query 5: Publish Date before Now AND After 2000 */
    task = new TaskAdapter() {
      public IStatus run(IProgressMonitor monitor) {
        List<ISearchCondition> conditions = new ArrayList<ISearchCondition>();

        ISearchField field1 = factory.createSearchField(INews.PUBLISH_DATE, INews.class.getName());
        conditions.add(factory.createSearchCondition(field1, SearchSpecifier.IS_BEFORE, new Date()));

        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.YEAR, 2000);

        ISearchField field2 = factory.createSearchField(INews.PUBLISH_DATE, INews.class.getName());
        conditions.add(factory.createSearchCondition(field2, SearchSpecifier.IS_AFTER, cal.getTime()));

        results[0] = fModelSearch.searchNews(conditions, true).size();

        return Status.OK_STATUS;
      }
    };
    tasks.clear();
    tasks.add(task);
    System.gc();
    long l5 = TestUtils.executeAndWait(tasks, 1);
    System.out.println("Searching [Date Range (" + results[0] + " results, Occur.MUST, Cold)] in " + FEEDS + " Feeds took: " + l5 + "ms");

    /* Recreate */
    Owl.getPersistenceService().recreateSchema();
    saveFeedsHelper();

    /* Query 6: News is *new*, *unread*, *updated* and Has Attachments IS TRUE */
    task = new TaskAdapter() {
      public IStatus run(IProgressMonitor monitor) {
        List<ISearchCondition> conditions = new ArrayList<ISearchCondition>();

        ISearchField field1 = factory.createSearchField(INews.STATE, INews.class.getName());
        conditions.add(factory.createSearchCondition(field1, SearchSpecifier.IS, EnumSet.of(INews.State.NEW, INews.State.UNREAD, INews.State.UPDATED)));

        ISearchField field4 = factory.createSearchField(INews.HAS_ATTACHMENTS, INews.class.getName());
        conditions.add(factory.createSearchCondition(field4, SearchSpecifier.IS, true));

        results[0] = fModelSearch.searchNews(conditions, false).size();

        return Status.OK_STATUS;
      }
    };
    tasks.clear();
    tasks.add(task);
    long l6 = TestUtils.executeAndWait(tasks, 1);
    System.out.println("Searching [States, Has Attachments (" + results[0] + " results, Occur.SHOULD, Cold)] in " + FEEDS + " Feeds took: " + l6 + "ms\n");

    if (ex.size() > 0)
      throw ex.get(0);
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void reloadFeedsNoRetention() throws Exception {
    List<ITask> tasks = getReloadFeedsTasks(false);

    /* Cold-Start: Interpret 216 Feeds */
    System.out.println("Reloading Feeds (No Retention): " + FEEDS + " Feeds [Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    Owl.getPersistenceService().recreateSchema();
    tasks = getReloadFeedsTasks(false);
    long l1 = TestUtils.executeAndWait(tasks, JOBS);

    Owl.getPersistenceService().recreateSchema();
    tasks = getReloadFeedsTasks(false);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println("Reloading Feeds (No Retention): " + FEEDS + " Feeds [Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms\n");
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void reloadFeedsWithRetention() throws Exception {
    List<ITask> tasks = getReloadFeedsTasks(true);

    /* Cold-Start: Interpret 216 Feeds */
    System.out.println("Reloading Feeds (With Retention): " + FEEDS + " Feeds [Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    Owl.getPersistenceService().recreateSchema();
    tasks = getReloadFeedsTasks(true);
    long l1 = TestUtils.executeAndWait(tasks, JOBS);

    Owl.getPersistenceService().recreateSchema();
    tasks = getReloadFeedsTasks(true);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println("Reloading Feeds (With Retention): " + FEEDS + " Feeds [Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms\n");
  }

  private List<ITask> getReloadFeedsTasks(boolean withRetention) {
    List<ITask> tasks = new ArrayList<ITask>();
    Random rand = new Random();

    /* Create Folder with all Bookmarks */
    IFolder rootFolder = new Folder(null, null, "Root");
    for (int i = 1; i < FEEDS + 1; i++) {
      try {
        URI feedLink = fPluginLocation.resolve("data/performance/" + i + ".xml").toURL().toURI();

        IFeed feed = new Feed(feedLink);

        if (withRetention) {
          for (int j = 0; j < 10; j++) {
            INews news = new News(feed);
            news.setTitle("Random Title " + j);
            news.setDescription(getLongDecription());
            news.setLink(new URI("http://www." + System.currentTimeMillis() + ".com/" + rand.nextInt(10000) + j));
            news.setComments("Comments");
            news.setState(INews.State.READ);
            feed.addNews(news);
          }
        }

        feed = DynamicDAO.save(feed);

        IBookMark bookmark = new BookMark(null, rootFolder, new FeedLinkReference(feed.getLink()), "Bookmark");

        if (withRetention)
          Owl.getPreferenceService().getEntityScope(bookmark).putBoolean(DefaultPreferences.DEL_READ_NEWS_STATE, true);

        rootFolder.addMark(bookmark, null, false);
        DynamicDAO.save(rootFolder);
      } catch (Exception e) {
        Activator.getDefault().logError(e.getMessage(), e);
      }
    }

    /* Create Tasks */
    List<IMark> marks = rootFolder.getMarks();
    for (IMark mark : marks) {
      if (mark instanceof IBookMark) {
        final IBookMark bookmark = (IBookMark) mark;

        tasks.add(new TaskAdapter() {
          public IStatus run(IProgressMonitor monitor) {
            return fController.reload(bookmark, null, new NullProgressMonitor());
          }
        });
      }
    }

    return tasks;
  }

  private String getLongDecription() {
    StringBuilder str = new StringBuilder();
    for (int i = 0; i < 10; i++)
      str.append("Hello World<br>");

    return str.toString();
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void setAllNewsStateWithEquiUpdateAndResolveFeed() throws Exception {
    List<ITask> tasks = getSetNewsStateTask(true, true, true);

    /* Cold-Start: Interpret 216 Feeds */
    String message = "Setting all news state by resolving feed (Update Equivalent): " + FEEDS + " Feeds ";
    System.out.println(message + "[Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    /* Warm-Start: Interpret 216 Feeds */
    Owl.getPersistenceService().recreateSchema();
    tasks = getSetNewsStateTask(true, true, true);
    long l1 = TestUtils.executeAndWait(tasks, JOBS);

    Owl.getPersistenceService().recreateSchema();
    tasks = getSetNewsStateTask(true, true, true);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println(message + "[Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms/n");
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void setNewsStateWithEquiUpdateAndResolveFeed() throws Exception {
    List<ITask> tasks = getSetNewsStateTask(true, true, false);

    /* Cold-Start: Interpret 216 Feeds */
    String message = "Setting 1/5 news state by resolving feed (Update Equivalent): " + FEEDS + " Feeds ";
    System.out.println(message + "[Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    /* Warm-Start: Interpret 216 Feeds */
    Owl.getPersistenceService().recreateSchema();
    tasks = getSetNewsStateTask(true, true, false);
    long l1 = TestUtils.executeAndWait(tasks, JOBS);

    Owl.getPersistenceService().recreateSchema();
    tasks = getSetNewsStateTask(true, true, false);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println(message + "[Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms/n");
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void setAllNewsStateWithEquiUpdate() throws Exception {
    List<ITask> tasks = getSetNewsStateTask(true, false, true);

    /* Cold-Start: Interpret 216 Feeds */
    String message = "Setting all news state (Update Equivalent): " + FEEDS + " Feeds ";
    System.out.println(message + "[Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    /* Warm-Start: Interpret 216 Feeds */
    Owl.getPersistenceService().recreateSchema();
    tasks = getSetNewsStateTask(true, false, true);
    long l1 = TestUtils.executeAndWait(tasks, JOBS);

    Owl.getPersistenceService().recreateSchema();
    tasks = getSetNewsStateTask(true, false, true);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println(message + "[Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms/n");
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void setNewsStateWithEquiUpdate() throws Exception {
    List<ITask> tasks = getSetNewsStateTask(true, false, false);

    /* Cold-Start: Interpret 216 Feeds */
    String message = "Setting 1/5 news state (Update Equivalent): " + FEEDS + " Feeds ";
    System.out.println(message + "[Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    /* Warm-Start: Interpret 216 Feeds */
    Owl.getPersistenceService().recreateSchema();
    tasks = getSetNewsStateTask(true, false, false);
    long l1 = TestUtils.executeAndWait(tasks, JOBS);

    Owl.getPersistenceService().recreateSchema();
    tasks = getSetNewsStateTask(true, false, false);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println(message + "[Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms/n");
  }

  private List<ITask> getSetNewsStateTask(final boolean updateEquivalent, final boolean resolveFeed, boolean allNewsNew) {

    final EnumSet<INews.State> unreadStates = EnumSet.of(INews.State.NEW, INews.State.UNREAD, INews.State.UPDATED);
    /* Save some Feeds first */
    List<IFeed> feeds = interpretFeedsHelper();
    final List<FeedLinkReference> feedRefs = new ArrayList<FeedLinkReference>();
    for (IFeed feed : feeds) {
      List<INews> news = feed.getNews();
      if (!allNewsNew && (!news.isEmpty())) {
        /* Make 4/5 of the INews READ */
        int endIndex = news.size() * 4 / 5;
        for (int i = 0; i < endIndex; ++i) {
          news.get(i).setState(INews.State.READ);
        }
      }
      feedRefs.add(new FeedLinkReference(DynamicDAO.save(feed).getLink()));
    }

    feeds = null;
    System.gc();

    final INewsDAO newsDAO = DynamicDAO.getDAO(INewsDAO.class);
    List<ITask> tasks = new ArrayList<ITask>();
    tasks.add(new TaskAdapter() {
      public IStatus run(IProgressMonitor monitor) {
        List<INews> news = new ArrayList<INews>();
        for (FeedLinkReference feedRef : feedRefs) {
          if (resolveFeed) {
            news.addAll(feedRef.resolve().getNewsByStates(unreadStates));
          } else {
            news.addAll(newsDAO.loadAll(feedRef, unreadStates));
          }
        }

        newsDAO.setState(news, INews.State.HIDDEN, updateEquivalent, false);

        return Status.OK_STATUS;
      }
    });

    return tasks;
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void setNewsStateWithoutEquiUpdate() throws Exception {
    List<ITask> tasks = getSetNewsStateTask(false, true, true);

    /* Cold-Start: Interpret 216 Feeds */
    System.out.println("Setting news state (Ignore Equivalent): " + FEEDS + " Feeds [Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    /* Warm-Start: Interpret 216 Feeds */
    Owl.getPersistenceService().recreateSchema();
    tasks = getSetNewsStateTask(false, true, true);
    long l1 = TestUtils.executeAndWait(tasks, JOBS);

    Owl.getPersistenceService().recreateSchema();
    tasks = getSetNewsStateTask(false, true, true);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println("Setting news state (Ignore Equivalent): " + FEEDS + " Feeds [Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms\n");
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void interpretFeeds() throws Exception {
    List<ITask> tasks = new ArrayList<ITask>();
    final List<Exception> ex = new ArrayList<Exception>();

    /* Prepare Tasks */
    for (int i = 1; i < FEEDS + 1; i++) {
      final int c = i;
      tasks.add(new TaskAdapter() {
        public IStatus run(IProgressMonitor monitor) {
          try {
            URI feedLink = fPluginLocation.resolve("data/performance/" + c + ".xml").toURL().toURI();
            IFeed feed = new Feed(feedLink);

            InputStream inS = loadFileProtocol(feed.getLink());
            Owl.getInterpreter().interpret(inS, feed, null);
          } catch (Exception e) {
            ex.add(e);
          }
          return Status.OK_STATUS;
        }
      });
    }

    /* Cold-Start: Interpret 216 Feeds */
    System.out.println("Interpreting " + FEEDS + " Feeds [Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    /* Warm-Start: Interpret 216 Feeds */
    long l1 = TestUtils.executeAndWait(tasks, JOBS);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println("Interpreting " + FEEDS + " Feeds [Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms\n");

    if (ex.size() > 0)
      throw ex.get(0);
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void saveFeeds() throws Exception {
    final List<Exception> ex = new ArrayList<Exception>();

    /* Cold-Start: Save 216 Feeds */
    List<ITask> tasks = getSaveFeedsTasks(ex);
    System.out.println("Saving " + FEEDS + " Feeds [Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    /* Warm-Start: Save 216 Feeds */
    Owl.getPersistenceService().recreateSchema();
    tasks = getSaveFeedsTasks(ex);
    long l1 = TestUtils.executeAndWait(tasks, JOBS);

    Owl.getPersistenceService().recreateSchema();
    tasks = getSaveFeedsTasks(ex);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println("Saving " + FEEDS + " Feeds [Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms\n");

    if (ex.size() > 0)
      throw ex.get(0);
  }

  private List<ITask> getSaveFeedsTasks(final List<Exception> ex) {
    List<ITask> tasks = new ArrayList<ITask>();
    List<IFeed> feeds = interpretFeedsHelper();

    for (final IFeed feed : feeds) {
      tasks.add(new TaskAdapter() {
        public IStatus run(IProgressMonitor monitor) {
          try {
            DynamicDAO.save(feed);
          } catch (Exception e) {
            ex.add(e);
          }
          return Status.OK_STATUS;
        }
      });
    }

    return tasks;
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void resolveFeeds() throws Exception {
    List<ITask> tasks = new ArrayList<ITask>();
    final List<Exception> ex = new ArrayList<Exception>();

    /* Prepare Tasks */
    List<FeedReference> feedRefs = saveFeedsHelper();
    for (final FeedReference feedRef : feedRefs) {
      tasks.add(new TaskAdapter() {
        public IStatus run(IProgressMonitor monitor) {
          try {
            accessAllFields(feedRef.resolve());
          } catch (Exception e) {
            ex.add(e);
          }
          return Status.OK_STATUS;
        }
      });
    }

    /* Cold-Start: Resolve 216 Feeds */
    System.gc();
    System.out.println("Resolving " + FEEDS + " Feeds [Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    /* Warm-Start: Resolve 216 Feeds */
    long l1 = TestUtils.executeAndWait(tasks, JOBS);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println("Resolving " + FEEDS + " Feeds [Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms\n");

    if (ex.size() > 0)
      throw ex.get(0);
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void resolveFeedsAndNews() throws Exception {
    List<ITask> tasks = new ArrayList<ITask>();
    final List<Exception> ex = new ArrayList<Exception>();

    /* Prepare Tasks */
    List<FeedReference> feedRefs = saveFeedsHelper();
    for (final FeedReference feedRef : feedRefs) {
      tasks.add(new TaskAdapter() {
        public IStatus run(IProgressMonitor monitor) {
          try {
            IFeed feed = feedRef.resolve();
            accessAllFields(feed);

            Collection<INews> news = feed.getNews();
            for (INews newsItem : news)
              accessAllFields(newsItem);
          } catch (Exception e) {
            ex.add(e);
          }
          return Status.OK_STATUS;
        }
      });
    }

    /* Cold-Start: Resolve 216 Feeds and all News */
    System.gc();
    System.out.println("Resolving " + FEEDS + " Feeds with all News [Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    /* Warm-Start: Resolve 216 Feeds and all News */
    long l1 = TestUtils.executeAndWait(tasks, JOBS);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println("Resolving " + FEEDS + " Feeds with all News [Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms\n");

    if (ex.size() > 0)
      throw ex.get(0);
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void resolveNewsStatesByResolving() throws Exception {
    List<ITask> tasks = new ArrayList<ITask>();
    final List<Exception> ex = new ArrayList<Exception>();

    /* Prepare Tasks */
    List<FeedReference> feedRefs = saveFeedsHelper();
    for (final FeedReference feedRef : feedRefs) {
      tasks.add(new TaskAdapter() {
        public IStatus run(IProgressMonitor monitor) {
          try {
            IFeed feed = feedRef.resolve();

            Collection<INews> news = feed.getNews();
            for (INews newsItem : news)
              newsItem.getState();
          } catch (Exception e) {
            ex.add(e);
          }
          return Status.OK_STATUS;
        }
      });
    }

    /* Cold-Start: Resolve 216 Feeds and all News */
    System.gc();
    System.out.println("Resolving News-States of " + FEEDS + " Feeds [Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    /* Warm-Start: Resolve 216 Feeds and all News */
    long l1 = TestUtils.executeAndWait(tasks, JOBS);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println("Resolving News-States of " + FEEDS + " Feeds [Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms\n");

    if (ex.size() > 0)
      throw ex.get(0);
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void resolveFeedCompletly() throws Exception {
    List<ITask> tasks = new ArrayList<ITask>();
    final List<Exception> ex = new ArrayList<Exception>();

    /* Prepare Tasks */
    List<FeedReference> feedRefs = saveFeedsHelper();
    for (final FeedReference feedRef : feedRefs) {
      tasks.add(new TaskAdapter() {
        public IStatus run(IProgressMonitor monitor) {
          accessAllFields(ex, feedRef);
          return Status.OK_STATUS;
        }
      });
    }

    /* Cold-Start: Resolve 216 Feeds and all News */
    System.gc();
    System.out.println("Resolving " + FEEDS + " Feeds with all News completly [Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    /* Warm-Start: Resolve 216 Feeds and all News */
    long l1 = TestUtils.executeAndWait(tasks, JOBS);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println("Resolving " + FEEDS + " Feeds with all News completly [Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms\n");

    if (ex.size() > 0)
      throw ex.get(0);
  }

  private void accessAllFields(final List<Exception> ex, final FeedReference feedRef) {
    try {
      IFeed feed = feedRef.resolve();

      if (feed.getAuthor() != null)
        accessAllFields(feed.getAuthor());

      List<ICategory> feedCats = feed.getCategories();
      for (ICategory category : feedCats)
        accessAllFields(category);

      if (feed.getImage() != null)
        accessAllFields(feed.getImage());

      accessAllFields(feed);

      Collection<INews> newsList = feed.getNews();
      for (INews news : newsList) {
        accessAllFields(news);

        List<IAttachment> attachments = news.getAttachments();
        for (IAttachment attachment : attachments)
          accessAllFields(attachment);

        if (news.getAuthor() != null)
          accessAllFields(news.getAuthor());

        List<ICategory> categories = news.getCategories();
        for (ICategory category : categories)
          accessAllFields(category);

        if (news.getGuid() != null)
          accessAllFields(news.getGuid());

        if (news.getSource() != null)
          accessAllFields(news.getSource());

        for (ILabel label : news.getLabels())
          accessAllFields(label);
      }
    } catch (Exception e) {
      ex.add(e);
    }
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void deleteFeeds() throws Exception {
    final List<Exception> ex = new ArrayList<Exception>();

    /* Cold-Start: Delete 216 Feeds */
    List<ITask> tasks = getDeleteFeedsTasks(ex);
    System.out.println("Deleting " + FEEDS + " Feeds [Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    /* Warm-Start: Delete 216 Feeds */
    Owl.getPersistenceService().recreateSchema();
    tasks = getDeleteFeedsTasks(ex);
    long l1 = TestUtils.executeAndWait(tasks, JOBS);

    Owl.getPersistenceService().recreateSchema();
    tasks = getDeleteFeedsTasks(ex);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println("Deleting " + FEEDS + " Feeds [Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms\n");

    if (ex.size() > 0)
      throw ex.get(0);
  }

  private List<ITask> getDeleteFeedsTasks(final List<Exception> ex) throws PersistenceException {
    List<ITask> tasks = new ArrayList<ITask>();

    List<FeedReference> feedRefs = saveFeedsHelper();
    for (final FeedReference feedRef : feedRefs) {
      tasks.add(new TaskAdapter() {
        public IStatus run(IProgressMonitor monitor) {
          try {
            DynamicDAO.delete(feedRef.resolve());
          } catch (Exception e) {
            ex.add(e);
          }
          return Status.OK_STATUS;
        }
      });
    }

    return tasks;
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void updateFeeds() throws Exception {
    final List<Exception> ex = new ArrayList<Exception>();

    /* Cold-Start: Update 216 Feeds */
    List<ITask> tasks = getUpdateFeedsTasks(ex);
    System.out.println("Updating " + FEEDS + " Feeds [Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    /* Warm-Start: Update 216 Feeds */
    Owl.getPersistenceService().recreateSchema();
    tasks = getUpdateFeedsTasks(ex);
    long l1 = TestUtils.executeAndWait(tasks, JOBS);

    Owl.getPersistenceService().recreateSchema();
    tasks = getUpdateFeedsTasks(ex);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println("Updating " + FEEDS + " Feeds [Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms\n");
    if (ex.size() > 0)
      throw ex.get(0);
  }

  @SuppressWarnings("nls")
  private List<ITask> getUpdateFeedsTasks(final List<Exception> ex) throws PersistenceException {
    List<ITask> tasks = new ArrayList<ITask>();

    /* Save some Feeds first */
    List<IFeed> feeds = interpretFeedsHelper();
    List<IFeed> savedFeeds = new ArrayList<IFeed>(feeds.size());
    for (IFeed feed : feeds)
      savedFeeds.add(DynamicDAO.save(feed));

    /* Interpret them again for updates */
    List<IFeed> newFeeds = interpretFeedsHelper();

    // To test pure updates on pure detached entities, replace newFeeds
    // with savedFeeds and comment out the existingFeed[0].merge(feed) inside
    // the task
    for (final IFeed feed : newFeeds) {
      final IFeed[] existingFeed = new IFeed[1];
      for (IFeed savedFeed : savedFeeds) {
        if (savedFeed.getLink().toString().equals(feed.getLink().toString())) {
          existingFeed[0] = savedFeed;

          // Enable this if you want to eliminate the Feed#merge time from
          // the test, must also comment this same line inside the task
          // existingFeed[0].merge(feed);
          // break;
        }
      }

      tasks.add(new TaskAdapter() {
        public IStatus run(IProgressMonitor monitor) {
          try {
            // Uncomment this line and comment the following one to use load the
            // full feed before the merge
            // existingFeed[0] =
            // feedManager.loadFullEntity(existingFeed[0].getId());
            existingFeed[0] = DynamicDAO.load(IFeed.class, existingFeed[0].getId());
            feed.setCopyright("The new Copyright");
            feed.setDescription("The Description has changed as well");
            feed.setPublishDate(new Date());

            if (feed.getNews().size() > 0) {
              feed.getNews().get(0).setDescription("Some new news description");
            }

            Owl.getModelFactory().createNews(null, feed, new Date()).setTitle("The New News");

            // Uncomment this line and comment out the next two to test the
            // performance of setting the id on a new entity to force
            // an update
            // DynamicDAO.save(feed);

            existingFeed[0].merge(feed);
            DynamicDAO.save(existingFeed[0]);
          } catch (Exception e) {
            ex.add(e);
          }
          return Status.OK_STATUS;
        }
      });
    }

    return tasks;
  }

  /**
   * @throws Exception
   */
  @SuppressWarnings("nls")
  @Test
  public void resolveSaveFeeds() throws Exception {
    final List<Exception> ex = new ArrayList<Exception>();

    /* Cold-Start: Save and Resolve 216 Feeds */
    List<ITask> tasks = getResolveSaveFeedsTasks(ex);
    System.gc();
    System.out.println("Saving/Resolving " + FEEDS / 2 + " Feeds [Cold - " + JOBS + " Jobs] took: " + TestUtils.executeAndWait(tasks, JOBS) + "ms");

    /* Warm-Start: Save and Resolve 216 Feeds */
    Owl.getPersistenceService().recreateSchema();
    tasks = getResolveSaveFeedsTasks(ex);
    long l1 = TestUtils.executeAndWait(tasks, JOBS);

    Owl.getPersistenceService().recreateSchema();
    tasks = getResolveSaveFeedsTasks(ex);
    long l2 = TestUtils.executeAndWait(tasks, JOBS);

    System.out.println("Saving/Resolving " + FEEDS / 2 + " Feeds [Warm - " + JOBS + " Jobs] took: " + (l1 + l2) / 2 + "ms\n");

    if (ex.size() > 0)
      throw ex.get(0);
  }

  private List<ITask> getResolveSaveFeedsTasks(final List<Exception> ex) throws PersistenceException {
    List<ITask> tasks = new ArrayList<ITask>();

    /* Save some Feeds first */
    final List<FeedReference> feedRefs = new ArrayList<FeedReference>();
    final List<IFeed> feeds = interpretFeedsHelper();
    final int limit = feeds.size() / 2;
    for (int i = 0; i < limit; i++)
      feedRefs.add(new FeedReference(DynamicDAO.save(feeds.get(i)).getId()));

    /* Tasks to resolve Feeds */
    for (int i = 0; i < limit; i++) {
      final int a = i;

      /* Add Task to save a Feed (88%) */
      if (a % 8 != 0) {
        tasks.add(new TaskAdapter() {
          public IStatus run(IProgressMonitor monitor) {
            try {
              DynamicDAO.save(feeds.get(a + limit));
            } catch (Exception e) {
              ex.add(e);
            }
            return Status.OK_STATUS;
          }
        });
      }

      /* Add Task to resolve a Feed (12%) */
      if (a % 8 == 0) {
        tasks.add(new TaskAdapter() {
          public IStatus run(IProgressMonitor monitor) {
            accessAllFields(ex, feedRefs.get(a));
            return Status.OK_STATUS;
          }
        });
      }
    }

    return tasks;
  }

  private List<FeedReference> saveFeedsHelper() throws PersistenceException {
    List<IFeed> feeds = interpretFeedsHelper();
    List<FeedReference> feedRefs = new ArrayList<FeedReference>();
    for (IFeed feed : feeds)
      feedRefs.add(new FeedReference(DynamicDAO.save(feed).getId()));

    return feedRefs;
  }

  @SuppressWarnings("nls")
  private List<IFeed> interpretFeedsHelper() {
    List<IFeed> feeds = new ArrayList<IFeed>();
    for (int i = 1; i < FEEDS + 1; i++) {
      try {
        URI feedLink = fPluginLocation.resolve("data/performance/" + i + ".xml").toURL().toURI();
        IFeed feed = new Feed(feedLink);

        InputStream inS = loadFileProtocol(feed.getLink());
        Owl.getInterpreter().interpret(inS, feed, null);

        feeds.add(feed);
      } catch (Exception e) {
        Activator.getDefault().logError(e.getMessage(), e);
      }
    }

    return feeds;
  }

  private void accessAllFields(IPersistable type) {
    if (type instanceof IEntity) {
      IEntity entity = (IEntity) type;
      entity.getId();
      Map<String, ?> properties = entity.getProperties();
      if (properties != null) {
        Set<String> keys = properties.keySet();
        for (String string : keys)
          properties.get(string);
      }
    }

    if (type instanceof IFeed) {
      IFeed feed = (IFeed) type;
      feed.getBase();
      feed.getCopyright();
      feed.getDaysToSkip();
      feed.getDescription();
      feed.getDocs();
      feed.getFormat();
      feed.getGenerator();
      feed.getHomepage();
      feed.getHoursToSkip();
      feed.getLanguage();
      feed.getLastBuildDate();
      feed.getLastModifiedDate();
      feed.getLink();
      feed.getProperties();
      feed.getPublishDate();
      feed.getRating();
      feed.getTitle();
      feed.getTTL();
      feed.getUpdateBase();
      feed.getUpdateFrequency();
      feed.getUpdatePeriod();
      feed.getWebmaster();
    }

    else if (type instanceof INews) {
      INews news = (INews) type;
      news.getBase();
      news.getComments();
      news.getDescription();
      news.getLink();
      news.getModifiedDate();
      news.getPublishDate();
      news.getRating();
      news.getReceiveDate();
      news.getState();
      news.getTitle();
    }

    else if (type instanceof IAttachment) {
      IAttachment attachment = (IAttachment) type;
      attachment.getLength();
      attachment.getType();
      attachment.getLink();
    }

    else if (type instanceof ICategory) {
      ICategory category = (ICategory) type;
      category.getDomain();
      category.getName();
    }

    else if (type instanceof ISource) {
      ISource source = (ISource) type;
      source.getName();
      source.getLink();
    }

    else if (type instanceof IPerson) {
      IPerson person = (IPerson) type;
      person.getEmail();
      person.getName();
      person.getUri();
    }

    else if (type instanceof IImage) {
      IImage image = (IImage) type;
      image.getDescription();
      image.getHeight();
      image.getWidth();
      image.getHomepage();
      image.getTitle();
      image.getLink();
    }

    else if (type instanceof ILabel) {
      ILabel label = (ILabel) type;
      label.getColor();
      label.getName();
    }

    else if (type instanceof IGuid) {
      IGuid guid = (IGuid) type;
      guid.getValue();
    }

    else if (type instanceof ICloud) {
      ICloud cloud = (ICloud) type;
      cloud.getDomain();
      cloud.getPath();
      cloud.getPort();
      cloud.getRegisterProcedure();
      cloud.getProtocol();
      cloud.getFeed();
    }

    else if (type instanceof ITextInput) {
      ITextInput input = (ITextInput) type;
      input.getDescription();
      input.getLink();
      input.getName();
      input.getTitle();
      input.getFeed();
    }
  }

  private InputStream loadFileProtocol(URI link) throws FileNotFoundException {
    File file = new File(link);
    return new BufferedInputStream(new FileInputStream(file));
  }
}
TOP

Related Classes of org.rssowl.core.tests.performance.PerformanceTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.