mitm.common.mail.repository.hibernate.MailRepositoryImplTest.java Source code

Java tutorial

Introduction

Here is the source code for mitm.common.mail.repository.hibernate.MailRepositoryImplTest.java

Source

/*
 * Copyright (c) 2010-2011, Martijn Brinkers, Djigzo.
 * 
 * This file is part of Djigzo email encryption.
 *
 * Djigzo is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License 
 * version 3, 19 November 2007 as published by the Free Software 
 * Foundation.
 *
 * Djigzo is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public 
 * License along with Djigzo. If not, see <http://www.gnu.org/licenses/>
 *
 * Additional permission under GNU AGPL version 3 section 7
 * 
 * If you modify this Program, or any covered work, by linking or 
 * combining it with aspectjrt.jar, aspectjweaver.jar, tyrex-1.0.3.jar, 
 * freemarker.jar, dom4j.jar, mx4j-jmx.jar, mx4j-tools.jar, 
 * spice-classman-1.0.jar, spice-loggerstore-0.5.jar, spice-salt-0.8.jar, 
 * spice-xmlpolicy-1.0.jar, saaj-api-1.3.jar, saaj-impl-1.3.jar, 
 * wsdl4j-1.6.1.jar (or modified versions of these libraries), 
 * containing parts covered by the terms of Eclipse Public License, 
 * tyrex license, freemarker license, dom4j license, mx4j license,
 * Spice Software License, Common Development and Distribution License
 * (CDDL), Common Public License (CPL) the licensors of this Program grant 
 * you additional permission to convey the resulting work.
 */
package mitm.common.mail.repository.hibernate;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import mitm.common.hibernate.HibernateSessionSource;
import mitm.common.hibernate.HibernateUtils;
import mitm.common.hibernate.SessionAdapter;
import mitm.common.hibernate.SessionAdapterFactory;
import mitm.common.hibernate.SessionManagedAutoCommitProxyFactory;
import mitm.common.hibernate.SessionManager;
import mitm.common.hibernate.SessionManagerImpl;
import mitm.common.hibernate.StandardHibernateSessionSourceImpl;
import mitm.common.hibernate.annotations.StartTransaction;
import mitm.common.mail.EmailAddressUtils;
import mitm.common.mail.MailSession;
import mitm.common.mail.MailUtils;
import mitm.common.mail.repository.MailRepository;
import mitm.common.mail.repository.MailRepositoryItem;
import mitm.common.mail.repository.MailRepositorySearchField;
import mitm.common.reflection.ProxyFactoryException;
import mitm.common.security.crypto.impl.RandomGeneratorImpl;
import mitm.common.util.IDGenerator;
import mitm.common.util.SizeUtils;
import mitm.common.util.UniqueIDGenerator;

import org.apache.commons.lang.time.DateUtils;
import org.apache.log4j.PropertyConfigurator;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class MailRepositoryImplTest {
    private static final File hibernateConfig = new File("test/resources/hibernate.cfg.xml");

    private static final File testBase = new File("test/resources/testdata/mail");

    private static final String DEFAULT_REPOSITORY = "quarantine";

    private static SessionManager sessionManager;
    private static AutoTransactDelegator proxy;
    private static IDGenerator idGenerator;

    private static MimeMessage loadMessage(String filename) throws FileNotFoundException, MessagingException {
        File mail = new File(testBase, filename);

        MimeMessage message = MailUtils.loadMessage(mail);

        return message;
    }

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        PropertyConfigurator.configure("conf/log4j.properties");

        HibernateSessionSource sessionSource = new StandardHibernateSessionSourceImpl(hibernateConfig);

        sessionManager = new SessionManagerImpl(sessionSource);

        HibernateUtils.recreateTables(sessionSource.getHibernateConfiguration());

        proxy = AutoTransactDelegator.createProxy();

        idGenerator = new UniqueIDGenerator(new RandomGeneratorImpl(), 16);
    }

    @Before
    public void setup() throws Exception {
        proxy.deleteAll();
    }

    public static class AutoTransactDelegator {
        public AutoTransactDelegator() {
            // required by AutoCommitProxyFactory
        }

        public static AutoTransactDelegator createProxy() throws ProxyFactoryException, NoSuchMethodException {
            AutoTransactDelegator autoTransactDelegator = new SessionManagedAutoCommitProxyFactory<AutoTransactDelegator>(
                    AutoTransactDelegator.class, sessionManager).createProxy();

            return autoTransactDelegator;
        }

        private MailRepositoryDAO getDAO() {
            SessionAdapter session = SessionAdapterFactory.create(sessionManager.getSession());

            return new MailRepositoryDAO(session);
        }

        private MailRepository getRepository(String repositoryName) {
            return new MailRepositoryImpl(idGenerator, sessionManager, repositoryName);
        }

        @StartTransaction
        public void deleteAll() {
            getDAO().deleteAll();
        }

        @StartTransaction
        public MailRepositoryItem createItem(String repositoryName, MimeMessage message)
                throws MessagingException, IOException {
            return getRepository(repositoryName).createItem(message);
        }

        @StartTransaction
        public MailRepositoryItem addItem(String repositoryName, MimeMessage message)
                throws MessagingException, IOException {
            MailRepository repository = getRepository(repositoryName);

            MailRepositoryItem item = repository.createItem(message);

            repository.addItem(item);

            return item;
        }

        @StartTransaction
        public MailRepositoryItem addItemWithDate(String repositoryName, MimeMessage message, Date created)
                throws MessagingException, IOException {
            MailRepository repository = getRepository(repositoryName);

            MailRepositoryItem item = ((MailRepositoryImpl) repository).createItem(message, created);

            repository.addItem(item);

            return item;
        }

        @StartTransaction
        public MailRepositoryItem addItem(String repositoryName, MimeMessage message, InternetAddress[] recipients,
                InternetAddress sender, String remoteAddress, Date lastUpdated, byte[] additionalData)
                throws MessagingException, IOException {
            MailRepository repository = getRepository(repositoryName);

            MailRepositoryItem item = repository.createItem(message);

            item.setRecipients(Arrays.asList(recipients));
            item.setSender(sender);
            item.setRemoteAddress(remoteAddress);
            item.setLastUpdated(lastUpdated);
            item.setAdditionalData(additionalData);

            repository.addItem(item);

            return item;
        }

        @StartTransaction
        public void deleteItem(String repositoryName, String id) throws MessagingException, IOException {
            getRepository(repositoryName).deleteItem(id);
        }

        @StartTransaction
        public MailRepositoryItem getItem(String repositoryName, String id) throws MessagingException, IOException {
            return getRepository(repositoryName).getItem(id);
        }

        @StartTransaction
        public int getItemCount(String repositoryName) {
            return getRepository(repositoryName).getItemCount();
        }

        @StartTransaction
        public List<String> getRecipients(String repositoryName, String id) throws MessagingException, IOException {
            MailRepositoryItem item = getItem(repositoryName, id);

            return EmailAddressUtils.addressesToStrings(item.getRecipients(), true);
        }

        @StartTransaction
        public List<? extends MailRepositoryItem> getItems(String repositoryName, Integer firstResult,
                Integer maxResults) {
            return getRepository(repositoryName).getItems(firstResult, maxResults);
        }

        @StartTransaction
        public List<? extends MailRepositoryItem> searchItems(String repositoryName,
                MailRepositorySearchField searchField, String key, Integer firstResult, Integer maxResults) {
            return getRepository(repositoryName).searchItems(searchField, key, firstResult, maxResults);
        }

        @StartTransaction
        public int getSearchCount(String repositoryName, MailRepositorySearchField searchField, String key) {
            return getRepository(repositoryName).getSearchCount(searchField, key);
        }

        @StartTransaction
        public List<? extends MailRepositoryItem> getItemsBefore(String repositoryName, Date before,
                Integer firstResult, Integer maxResults) {
            return getRepository(repositoryName).getItemsBefore(before, firstResult, maxResults);
        }

        @StartTransaction
        public void assertMessage(String repositoryName, String id, MimeMessage expected)
                throws MessagingException, IOException {
            MailRepositoryItem item = getItem(repositoryName, id);

            ByteArrayOutputStream bos1 = new ByteArrayOutputStream();

            MailUtils.writeMessage(item.getMimeMessage(), bos1);

            ByteArrayOutputStream bos2 = new ByteArrayOutputStream();

            MailUtils.writeMessage(expected, bos2);

            assertTrue(Arrays.equals(bos2.toByteArray(), bos1.toByteArray()));
        }
    }

    @Test
    public void testCreateItem() throws Exception {
        MimeMessage message = loadMessage("html-alternative.eml");

        assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY));

        MailRepositoryItem item = proxy.createItem(DEFAULT_REPOSITORY, message);

        assertNotNull(item);
        assertNotNull(item.getID());
        assertNotNull(item.getCreated());

        assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY));
    }

    @Test
    public void testAddItem() throws Exception {
        MimeMessage message = loadMessage("html-alternative.eml");

        assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY));

        MailRepositoryItem item = proxy.addItem(DEFAULT_REPOSITORY, message);

        assertNotNull(item);

        assertEquals(1, proxy.getItemCount(DEFAULT_REPOSITORY));

        assertEquals("Open Source Group Members <group-digests@linkedin.com>", item.getFromHeader());
        assertEquals("From Joshua Barger and other Open Source group members on LinkedIn", item.getSubject());
        assertEquals("<1266236208.59156794.1253209950952.JavaMail.app@ech3-cdn18.prod>", item.getMessageID());

        item = proxy.addItem(DEFAULT_REPOSITORY, message);

        assertNotNull(item);

        assertEquals(2, proxy.getItemCount(DEFAULT_REPOSITORY));
    }

    @Test
    public void testInvalidFrom() throws Exception {
        MimeMessage message = loadMessage("invalid-from-to-cc-reply-to.eml");

        assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY));

        MailRepositoryItem item = proxy.addItem(DEFAULT_REPOSITORY, message);

        assertNotNull(item);

        assertEquals(1, proxy.getItemCount(DEFAULT_REPOSITORY));

        assertEquals("\"%8787\" <&^&^&^&^&^&)\"(&@^%##()||", item.getFromHeader());
    }

    @Test
    public void testDeleteItem() throws Exception {
        MimeMessage message = loadMessage("html-alternative.eml");

        assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY));

        MailRepositoryItem item = proxy.addItem(DEFAULT_REPOSITORY, message);

        assertNotNull(item);

        assertEquals(1, proxy.getItemCount(DEFAULT_REPOSITORY));

        proxy.deleteItem(DEFAULT_REPOSITORY, item.getID());

        assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY));
    }

    @Test
    public void testGetItem() throws Exception {
        MimeMessage message = loadMessage("html-alternative.eml");

        assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY));

        MailRepositoryItem item = proxy.addItem(DEFAULT_REPOSITORY, message,
                InternetAddress.parse("test1@example.com, test2@example.com", false),
                new InternetAddress("sender@example.com"), "127.0.0.1", new Date(123456), new byte[] { 1, 2, 3 });

        MailRepositoryItem item2 = proxy.getItem(DEFAULT_REPOSITORY, item.getID());

        assertNotNull(item2);

        assertEquals("Open Source Group Members <group-digests@linkedin.com>", item2.getFromHeader());
        assertEquals("From Joshua Barger and other Open Source group members on LinkedIn", item2.getSubject());
        assertEquals("<1266236208.59156794.1253209950952.JavaMail.app@ech3-cdn18.prod>", item2.getMessageID());
        assertEquals("sender@example.com", item2.getSender().getAddress());
        assertEquals("127.0.0.1", item2.getRemoteAddress());
        assertEquals(123456, item2.getLastUpdated().getTime());
        assertTrue(Arrays.equals(new byte[] { 1, 2, 3 }, item2.getAdditionalData()));

        assertEquals("[test1@example.com, test2@example.com]",
                proxy.getRecipients(DEFAULT_REPOSITORY, item2.getID()).toString());

        proxy.assertMessage(DEFAULT_REPOSITORY, item2.getID(), message);
    }

    @Test
    public void testGetItems() throws Exception {
        MimeMessage message = loadMessage("html-alternative.eml");

        assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY));

        int nrOfItems = 10;

        for (int i = 0; i < nrOfItems; i++) {
            proxy.addItem(DEFAULT_REPOSITORY, message,
                    InternetAddress.parse("test1@example.com, test2@example.com", false), null, Integer.toString(i),
                    null, null);
        }

        assertEquals(nrOfItems, proxy.getItemCount(DEFAULT_REPOSITORY));

        List<? extends MailRepositoryItem> items = proxy.getItems(DEFAULT_REPOSITORY, 0, Integer.MAX_VALUE);

        assertEquals(nrOfItems, items.size());

        for (int i = 0; i < nrOfItems; i++) {
            MailRepositoryItem item = items.get(i);

            assertEquals(Integer.toString(i), item.getRemoteAddress());
        }

        items = proxy.getItems(DEFAULT_REPOSITORY, 0, 1);

        assertEquals(1, items.size());

        items = proxy.getItems(DEFAULT_REPOSITORY, 8, 100);

        assertEquals(2, items.size());

        assertEquals("8", items.get(0).getRemoteAddress());
        assertEquals("9", items.get(1).getRemoteAddress());
    }

    @Test
    public void testSearch() throws Exception {
        MimeMessage message = loadMessage("html-alternative.eml");

        assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY));

        int nrOfItems = 10;

        for (int i = 0; i < nrOfItems; i++) {
            proxy.addItem(DEFAULT_REPOSITORY, message,
                    InternetAddress.parse("test" + i + "@example.com, other@example.com", false),
                    new InternetAddress("sender" + i + "@example.com", false), "127.0.0." + i, null, null);
        }

        assertEquals(nrOfItems, proxy.getItemCount(DEFAULT_REPOSITORY));

        // search from 
        List<? extends MailRepositoryItem> items = proxy.searchItems(DEFAULT_REPOSITORY,
                MailRepositorySearchField.FROM, "%linkedin%", 0, Integer.MAX_VALUE);
        assertEquals(10, items.size());

        // search from no hits
        items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.FROM, "linkedin", 0,
                Integer.MAX_VALUE);
        assertEquals(0, items.size());

        // search message ID
        items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.MESSAGE_ID,
                "<1266236208.59156794.1253209950952.JavaMail.app@ech3-cdn18.prod>", 3, 2);
        assertEquals(2, items.size());

        // search subject
        items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.SUBJECT, "%OPEN SOURCE GROUP%", 3,
                Integer.MAX_VALUE);
        assertEquals(7, items.size());

        // search sender
        items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.SENDER, "sender4@example.com", 0,
                Integer.MAX_VALUE);
        assertEquals(1, items.size());
        assertEquals("127.0.0.4", items.get(0).getRemoteAddress());

        // search recipients
        items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.RECIPIENTS, "test5@example.com", 0,
                Integer.MAX_VALUE);
        assertEquals(1, items.size());
        assertEquals("127.0.0.5", items.get(0).getRemoteAddress());

        // search recipients
        items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.RECIPIENTS, "other@example.com", 5,
                Integer.MAX_VALUE);
        assertEquals(5, items.size());
    }

    @Test
    public void testSearchCount() throws Exception {
        MimeMessage message = loadMessage("html-alternative.eml");

        assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY));

        int nrOfItems = 10;

        for (int i = 0; i < nrOfItems; i++) {
            proxy.addItem(DEFAULT_REPOSITORY, message,
                    InternetAddress.parse("test" + i + "@example.com, other@example.com", false),
                    new InternetAddress("sender" + i + "@example.com", false), "127.0.0." + i, null, null);
        }

        assertEquals(nrOfItems, proxy.getItemCount(DEFAULT_REPOSITORY));
        // search from 
        assertEquals(10, proxy.getSearchCount(DEFAULT_REPOSITORY, MailRepositorySearchField.FROM, "%linkedin%"));

        // search from no hits
        assertEquals(0, proxy.getSearchCount(DEFAULT_REPOSITORY, MailRepositorySearchField.FROM, "linkedin"));

        // search message ID
        assertEquals(10, proxy.getSearchCount(DEFAULT_REPOSITORY, MailRepositorySearchField.MESSAGE_ID,
                "<1266236208.59156794.1253209950952.JavaMail.app@ech3-cdn18.prod>"));

        // search subject
        assertEquals(10,
                proxy.getSearchCount(DEFAULT_REPOSITORY, MailRepositorySearchField.SUBJECT, "%OPEN SOURCE GROUP%"));

        // search sender
        assertEquals(1,
                proxy.getSearchCount(DEFAULT_REPOSITORY, MailRepositorySearchField.SENDER, "sender4@example.com"));

        // search recipients
        assertEquals(1, proxy.getSearchCount(DEFAULT_REPOSITORY, MailRepositorySearchField.RECIPIENTS,
                "test5@example.com"));

        // search recipients
        assertEquals(10, proxy.getSearchCount(DEFAULT_REPOSITORY, MailRepositorySearchField.RECIPIENTS,
                "other@example.com"));
    }

    @Test
    public void testSorting() throws Exception {
        MimeMessage message = loadMessage("html-alternative.eml");

        assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY));

        Date now = new Date();

        MailRepositoryItem item4 = proxy.addItemWithDate(DEFAULT_REPOSITORY, message, DateUtils.addHours(now, 1));

        MailRepositoryItem item3 = proxy.addItemWithDate(DEFAULT_REPOSITORY, message, now);

        MailRepositoryItem item2 = proxy.addItemWithDate(DEFAULT_REPOSITORY, message, DateUtils.addHours(now, -1));

        MailRepositoryItem item1 = proxy.addItemWithDate(DEFAULT_REPOSITORY, message, DateUtils.addHours(now, -2));

        assertEquals(4, proxy.getItemCount(DEFAULT_REPOSITORY));

        List<? extends MailRepositoryItem> items = proxy.getItems(DEFAULT_REPOSITORY, 0, Integer.MAX_VALUE);

        assertEquals(4, items.size());

        assertEquals(item1.getID(), items.get(0).getID());
        assertEquals(item2.getID(), items.get(1).getID());
        assertEquals(item3.getID(), items.get(2).getID());
        assertEquals(item4.getID(), items.get(3).getID());

        items = proxy.getItems(DEFAULT_REPOSITORY, 2, Integer.MAX_VALUE);

        assertEquals(2, items.size());
        assertEquals(item3.getID(), items.get(0).getID());
        assertEquals(item4.getID(), items.get(1).getID());

        items = proxy.searchItems(DEFAULT_REPOSITORY, MailRepositorySearchField.FROM, "%linkedin%", 0,
                Integer.MAX_VALUE);

        assertEquals(4, items.size());

        assertEquals(item1.getID(), items.get(0).getID());
        assertEquals(item2.getID(), items.get(1).getID());
        assertEquals(item3.getID(), items.get(2).getID());
        assertEquals(item4.getID(), items.get(3).getID());
    }

    @Test
    public void testBefore() throws Exception {
        MimeMessage message = loadMessage("html-alternative.eml");

        assertEquals(0, proxy.getItemCount(DEFAULT_REPOSITORY));

        Date now = new Date();

        proxy.addItemWithDate(DEFAULT_REPOSITORY, message, DateUtils.addHours(now, 1));

        proxy.addItemWithDate(DEFAULT_REPOSITORY, message, now);

        MailRepositoryItem item2 = proxy.addItemWithDate(DEFAULT_REPOSITORY, message, DateUtils.addHours(now, -1));

        MailRepositoryItem item1 = proxy.addItemWithDate(DEFAULT_REPOSITORY, message, DateUtils.addHours(now, -2));

        assertEquals(4, proxy.getItemCount(DEFAULT_REPOSITORY));

        List<? extends MailRepositoryItem> items = proxy.getItemsBefore(DEFAULT_REPOSITORY, now, 0,
                Integer.MAX_VALUE);

        assertEquals(2, items.size());

        assertEquals(item1.getID(), items.get(0).getID());
        assertEquals(item2.getID(), items.get(1).getID());
    }

    /*
     * Insert very large messages and check the speed of inserting and loading and whether loading all messages 
     * does not result in a OOM (i.e., the messages should be lazy loaded).
     */
    @Test
    public void testPerformance() throws Exception {
        MimeMessage message = new MimeMessage(MailSession.getDefaultSession());

        int messageSize = 50 * SizeUtils.MB;

        byte[] content = new byte[messageSize];

        Arrays.fill(content, (byte) 'A');

        message.setContent(content, "application/octet-stream");
        message.saveChanges();
        MailUtils.validateMessage(message);

        long start = System.currentTimeMillis();

        int nrOfItems = 10;

        for (int i = 0; i < nrOfItems; i++) {
            proxy.addItem(DEFAULT_REPOSITORY, message,
                    InternetAddress.parse("test" + i + "@example.com, other@example.com", false),
                    new InternetAddress("sender" + i + "@example.com", false), "127.0.0." + i, null, null);
        }

        double msec = (double) (System.currentTimeMillis() - start) / nrOfItems;

        System.out.println("msec / add:" + msec);

        assertTrue("Can fail on slower systems", msec < 10000);

        start = System.currentTimeMillis();

        List<? extends MailRepositoryItem> items = proxy.getItems(DEFAULT_REPOSITORY, 0, Integer.MAX_VALUE);

        for (MailRepositoryItem item : items) {
            System.out.println(item.getID());
        }

        msec = (double) (System.currentTimeMillis() - start) / nrOfItems;

        System.out.println("msec / get:" + msec);

        assertTrue("Can fail on slower systems", msec < 100);
    }
}