You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by bt...@apache.org on 2017/06/21 08:01:24 UTC
[1/3] james-project git commit: JAMES-2063 Add tests on
SelectedMailboxImpl for concurrent events
Repository: james-project
Updated Branches:
refs/heads/master ce408bf81 -> be37b9c0c
JAMES-2063 Add tests on SelectedMailboxImpl for concurrent events
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/b74db024
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/b74db024
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/b74db024
Branch: refs/heads/master
Commit: b74db024409fea9edeb84c571eb02e4863391ca6
Parents: ce408bf
Author: benwa <bt...@linagora.com>
Authored: Tue Jun 20 10:49:28 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Tue Jun 20 11:47:24 2017 +0700
----------------------------------------------------------------------
protocols/imap/pom.xml | 5 +
.../processor/base/SelectedMailboxImplTest.java | 172 +++++++++++++++++++
2 files changed, 177 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/b74db024/protocols/imap/pom.xml
----------------------------------------------------------------------
diff --git a/protocols/imap/pom.xml b/protocols/imap/pom.xml
index c2f590d..12b9826 100644
--- a/protocols/imap/pom.xml
+++ b/protocols/imap/pom.xml
@@ -75,6 +75,11 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>commons-codec</groupId>
http://git-wip-us.apache.org/repos/asf/james-project/blob/b74db024/protocols/imap/src/test/java/org/apache/james/imap/processor/base/SelectedMailboxImplTest.java
----------------------------------------------------------------------
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/base/SelectedMailboxImplTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/base/SelectedMailboxImplTest.java
new file mode 100644
index 0000000..a9e7144
--- /dev/null
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/base/SelectedMailboxImplTest.java
@@ -0,0 +1,172 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.imap.processor.base;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Date;
+import java.util.Iterator;
+import java.util.TreeMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.mail.Flags;
+
+import org.apache.james.imap.api.ImapSessionUtils;
+import org.apache.james.imap.api.process.ImapSession;
+import org.apache.james.mailbox.MailboxListener;
+import org.apache.james.mailbox.MailboxManager;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.MessageUid;
+import org.apache.james.mailbox.model.MailboxConstants;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.MessageMetaData;
+import org.apache.james.mailbox.model.SearchQuery;
+import org.apache.james.mailbox.store.SimpleMessageMetaData;
+import org.apache.james.mailbox.store.event.EventFactory;
+import org.apache.james.mailbox.store.mail.model.DefaultMessageId;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+
+
+public class SelectedMailboxImplTest {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SelectedMailboxImplTest.class);
+ public static final MessageUid MESSAGE_UID_5 = MessageUid.of(5);
+
+ private ExecutorService executorService;
+ private MailboxManager mailboxManager;
+ private MessageManager messageManager;
+ private MailboxPath mailboxPath;
+ private ImapSession imapSession;
+ private Mailbox mailbox;
+
+ @Before
+ public void setUp() throws Exception {
+ executorService = Executors.newFixedThreadPool(1);
+
+ mailboxPath = new MailboxPath(MailboxConstants.USER_NAMESPACE, "tellier@linagora.com", MailboxConstants.INBOX);
+ mailboxManager = mock(MailboxManager.class);
+ messageManager = mock(MessageManager.class);
+ when(mailboxManager.getMailbox(eq(mailboxPath), any(MailboxSession.class))).thenReturn(messageManager);
+ when(messageManager.getApplicableFlags(any(MailboxSession.class))).thenReturn(new Flags());
+ when(messageManager.search(any(SearchQuery.class), any(MailboxSession.class)))
+ .then(sleepThenSearchAnswer());
+
+ imapSession = mock(ImapSession.class);
+ when(imapSession.getAttribute(ImapSessionUtils.MAILBOX_SESSION_ATTRIBUTE_SESSION_KEY)).thenReturn(mock(MailboxSession.class));
+
+ mailbox = mock(Mailbox.class);
+ when(mailbox.generateAssociatedPath()).thenReturn(mailboxPath);
+ }
+
+ @After
+ public void tearDown() {
+ executorService.shutdownNow();
+ }
+
+ @Ignore
+ @Test
+ public void concurrentEventShouldNotSkipUidEmmitedDuringInitialization() throws Exception {
+ final AtomicInteger success = new AtomicInteger(0);
+ doAnswer(generateEmitEventAnswer(success))
+ .when(mailboxManager)
+ .addListener(eq(mailboxPath), any(MailboxListener.class), any(MailboxSession.class));
+
+ SelectedMailboxImpl selectedMailbox = new SelectedMailboxImpl(
+ mailboxManager,
+ imapSession,
+ mailboxPath);
+
+ assertThat(selectedMailbox.getLastUid().get()).isEqualTo(MESSAGE_UID_5);
+ }
+
+ @Ignore
+ @Test
+ public void concurrentEventShouldBeSupportedDuringInitialisation() throws Exception {
+ final AtomicInteger success = new AtomicInteger(0);
+ doAnswer(generateEmitEventAnswer(success))
+ .when(mailboxManager)
+ .addListener(eq(mailboxPath), any(MailboxListener.class), any(MailboxSession.class));
+
+ new SelectedMailboxImpl(
+ mailboxManager,
+ imapSession,
+ mailboxPath);
+
+ assertThat(success.get())
+ .as("Get the incremented value in case of successful event processing.")
+ .isEqualTo(1);
+ }
+
+ private Answer<Iterator<MessageUid>> sleepThenSearchAnswer() {
+ return new Answer<Iterator<MessageUid>>() {
+ @Override
+ public Iterator<MessageUid> answer(InvocationOnMock invocation) throws Throwable {
+ Thread.sleep(1000);
+ return ImmutableList.of(MessageUid.of(1), MessageUid.of(3)).iterator();
+ }
+ };
+ }
+
+ private Answer generateEmitEventAnswer(final AtomicInteger success) {
+ return new Answer() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ Object[] args = invocation.getArguments();
+ final MailboxListener mailboxListener = (MailboxListener) args[1];
+ executorService.submit(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ emitEvent(mailboxListener);
+ success.incrementAndGet();
+ } catch (Exception e) {
+ LOGGER.error("Error while processing event on a concurrent thread", e);
+ }
+ }
+ });
+ return null;
+ }
+ };
+ }
+
+ private void emitEvent(MailboxListener mailboxListener) {
+ TreeMap<MessageUid, MessageMetaData> result = new TreeMap<MessageUid, MessageMetaData>();
+ result.put(MESSAGE_UID_5, new SimpleMessageMetaData(MESSAGE_UID_5, 12, new Flags(), 38, new Date(), new DefaultMessageId()));
+ mailboxListener.event(new EventFactory().added(mock(MailboxSession.class), result, mailbox));
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[3/3] james-project git commit: JAMES-2058 Add new page on the
website to configure Spring JPA with Postgres
Posted by bt...@apache.org.
JAMES-2058 Add new page on the website to configure Spring JPA with Postgres
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/be37b9c0
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/be37b9c0
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/be37b9c0
Branch: refs/heads/master
Commit: be37b9c0c1d6eb50df4ea06761b9b8013a7b6b0d
Parents: 53d7536
Author: quynhn <qn...@linagora.com>
Authored: Thu Jun 15 17:58:37 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Jun 21 14:59:04 2017 +0700
----------------------------------------------------------------------
src/site/site.xml | 1 +
.../xdoc/server/config-spring-jpa-postgres.xml | 109 +++++++++++++++++++
2 files changed, 110 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/be37b9c0/src/site/site.xml
----------------------------------------------------------------------
diff --git a/src/site/site.xml b/src/site/site.xml
index b73abec..9b7fd05 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -134,6 +134,7 @@
<item name="Guice" href="/server/config-guice.html" />
<item name="ElasticSearch" href="/server/config-elasticsearch.html" />
<item name="Cassandra" href="/server/config-cassandra.html" />
+ <item name="Spring JPA Postgres" href="/server/config-spring-jpa-postgres.html" />
<item name="Quota" href="/server/config-quota.html" />
<item name="Events" href="/server/config-events.html" />
</item>
http://git-wip-us.apache.org/repos/asf/james-project/blob/be37b9c0/src/site/xdoc/server/config-spring-jpa-postgres.xml
----------------------------------------------------------------------
diff --git a/src/site/xdoc/server/config-spring-jpa-postgres.xml b/src/site/xdoc/server/config-spring-jpa-postgres.xml
new file mode 100644
index 0000000..d88824a
--- /dev/null
+++ b/src/site/xdoc/server/config-spring-jpa-postgres.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<document>
+
+ <properties>
+ <title>Apache James Server 3 - Spring JPA With Postgres Configuration</title>
+ </properties>
+
+<body>
+
+
+ <section name="Introduction">
+ <p>Consult <a href="http://james.apache.org/server/config-system.html">System Configuration</a> to get template, some examples and hints for the configuration with JPA.</p>
+ </section>
+
+ <section name="Current Supported Relational Database">
+ <p>James supports Derby as a default database, you do not need to do any additional configuration if you are using Derby</p>
+ </section>
+
+ <section name="Spring JPA With Postgres Configuration">
+ <p>If you wish to use Postgres as a database, please follow those steps to configure it</p>
+ <subsection name="Step 1: Create database on Postgres">
+
+ <p>You need to install Postgres or run Postgres with Docker</p>
+
+ <p>Example to install it on Debian:</p>
+ <source>
+ sudo apt-get update && sudo apt-get install postgresql-9.4 postgresql-client-9.4
+ </source>
+ <p>Example to pull and launch Postgres on docker</p>
+ <source>
+ docker run --detach --name postgres library/postgres
+ </source>
+ <p>Postgres does not create database on the fly so you need to create the database manually if it does not exist. Here is the command to perform this action: </p>
+
+ <source>psql --username postgres --tuples-only --command "SELECT 1 FROM pg_database WHERE dataname = '<strong><italic>database_name</italic></strong>'" \
+ | grep -q 1 || psql --username postgres --command "CREATE DATABASE <strong><italic>database_name</italic></strong>"</source>
+
+ <dl>
+ <dt><strong>database_name</strong></dt>
+ <dd>The name of database</dd>
+ </dl>
+
+ </subsection>
+
+ <subsection name="Step 2: Point to the database in configuration file">
+ <p>Change the content of <italic>james-database.properties</italic> and point to the 'database_name' created earlier</p>
+ <source>
+ database.driverClassName=org.postgresql.Driver
+ database.url=jdbc:postgresql://<strong>ip_of_postgres</strong>/<strong>database_name</strong>
+ database.username=postgres
+ database.password=postgres
+
+ vendorAdapter.database=POSTGRESQL
+ </source>
+ <p>If you are using the James Spring docker image. You need to customise the configuration file of the docker container with those steps:</p>
+ <ul>
+ <li>Create a new james-database.properties file with above content</li>
+ <li>Then you can add the configuration file to docker container using --volume flag</li>
+ <source>
+ --volume path_to_folder_which_contain_configuration_file/james-database.properties:/root/james-server-app-3.0.0-RC2-SNAPSHOT/conf/james-database.properties
+ </source>
+ </ul>
+ </subsection>
+
+ <subsection name="Step 3: Copy driver class to the right place">
+ <p>Follow this link <a href="https://jdbc.postgresql.org/download.html">Postgres Driver</a> to download the right version of the JDBC driver.</p>
+ <p>Copy that jar file to the <strong>conf/lib/</strong> folder of Spring James</p>
+ <p>If you are using the James Spring docker image, download the jar file then make it available on the classpath of your James instance using an additional docker volume: </p>
+ <source>
+ --volume path_to_folder_which_contain_jar_file/:/root/james-server-app-3.0.0-RC2-SNAPSHOT/conf/lib/
+ </source>
+ </subsection>
+
+ <subsection name="Step 4: Restart James">
+ <p>Follow the guide on <a href="http://james.apache.org/server/install.html">Restart and Testing</a> to restart James</p>
+
+ <p>If you are using the James Spring docker image, launch James docker or just stop and start docker container again if it ran. </p>
+
+ <p>Example to launch James Spring docker image with the volume</p>
+ <source>
+ docker run --volume path_to_folder_which_contain_configuration_file/james-database.properties:/root/james-server-app-3.0.0-RC2-SNAPSHOT/conf/james-database.properties \
+ --volume path_to_folder_which_contain_jar_file/:/root/james-server-app-3.0.0-RC2-SNAPSHOT/conf/lib/ \
+ --hostname localhost --publish "25:25" --publish "110:110" --publish "143:143" --publish "465:465" --publish "587:587" --publish "993:993" \
+ --name james_run linagora/james-jpa-spring
+ </source>
+ </subsection>
+ </section>
+
+</body>
+
+</document>
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org
[2/3] james-project git commit: JAMES-2063 SelectedMailboxImpl should
allow concurrent events when initializing
Posted by bt...@apache.org.
JAMES-2063 SelectedMailboxImpl should allow concurrent events when initializing
Also reduce lock contention. Avoid locking while building conversion and reading from the mailbox, to avoid delaying concurrent sessions.
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/53d75365
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/53d75365
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/53d75365
Branch: refs/heads/master
Commit: 53d75365fc2de63c5c8ab7205b91f2695e8dccd5
Parents: b74db02
Author: benwa <bt...@linagora.com>
Authored: Tue Jun 20 10:55:21 2017 +0700
Committer: benwa <bt...@linagora.com>
Committed: Wed Jun 21 14:58:20 2017 +0700
----------------------------------------------------------------------
protocols/imap/pom.xml | 5 +-
.../processor/base/SelectedMailboxImpl.java | 12 +-
.../imap/processor/base/UidMsnConverter.java | 17 ++-
.../processor/base/SelectedMailboxImplTest.java | 44 +++----
.../processor/base/UidMsnConverterTest.java | 120 ++++++++++++++++---
.../imap/src/test/resources/logback-test.xml | 24 ++++
6 files changed, 170 insertions(+), 52 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/james-project/blob/53d75365/protocols/imap/pom.xml
----------------------------------------------------------------------
diff --git a/protocols/imap/pom.xml b/protocols/imap/pom.xml
index 12b9826..78ac115 100644
--- a/protocols/imap/pom.xml
+++ b/protocols/imap/pom.xml
@@ -76,8 +76,9 @@
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-simple</artifactId>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.1.7</version>
<scope>test</scope>
</dependency>
http://git-wip-us.apache.org/repos/asf/james-project/blob/53d75365/protocols/imap/src/main/java/org/apache/james/imap/processor/base/SelectedMailboxImpl.java
----------------------------------------------------------------------
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/base/SelectedMailboxImpl.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/base/SelectedMailboxImpl.java
index d929b76..d56c6ef 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/base/SelectedMailboxImpl.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/base/SelectedMailboxImpl.java
@@ -44,6 +44,7 @@ import org.apache.james.mailbox.model.SearchQuery;
import org.apache.james.mailbox.model.UpdatedFlags;
import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
/**
* Default implementation of {@link SelectedMailbox}
@@ -84,17 +85,14 @@ public class SelectedMailboxImpl implements SelectedMailbox, MailboxListener{
MailboxSession mailboxSession = ImapSessionUtils.getMailboxSession(session);
+ uidMsnConverter = new UidMsnConverter();
+
mailboxManager.addListener(path, this, mailboxSession);
MessageManager messageManager = mailboxManager.getMailbox(path, mailboxSession);
applicableFlags = messageManager.getApplicableFlags(mailboxSession);
- uidMsnConverter = getUidMsnConverter(mailboxSession, messageManager);
- }
-
- private UidMsnConverter getUidMsnConverter(MailboxSession mailboxSession , MessageManager messageManager) throws MailboxException {
- return new UidMsnConverter(
- messageManager.search(
- new SearchQuery(SearchQuery.all()), mailboxSession));
+ uidMsnConverter.addAll(ImmutableList.copyOf(
+ messageManager.search(new SearchQuery(SearchQuery.all()), mailboxSession)));
}
@Override
http://git-wip-us.apache.org/repos/asf/james-project/blob/53d75365/protocols/imap/src/main/java/org/apache/james/imap/processor/base/UidMsnConverter.java
----------------------------------------------------------------------
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/base/UidMsnConverter.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/base/UidMsnConverter.java
index 9276e27..9e09053 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/base/UidMsnConverter.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/base/UidMsnConverter.java
@@ -21,7 +21,9 @@ package org.apache.james.imap.processor.base;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.TreeSet;
import org.apache.james.mailbox.MessageUid;
@@ -35,9 +37,16 @@ public class UidMsnConverter {
@VisibleForTesting final ArrayList<MessageUid> uids;
- public UidMsnConverter(Iterator<MessageUid> iterator) {
- uids = Lists.newArrayList(iterator);
- Collections.sort(uids);
+ public UidMsnConverter() {
+ this.uids = Lists.newArrayList();
+ }
+
+ public synchronized void addAll(List<MessageUid> addedUids) {
+ TreeSet<MessageUid> tmp = new TreeSet<MessageUid>();
+ tmp.addAll(uids);
+ tmp.addAll(addedUids);
+ uids.clear();
+ uids.addAll(tmp);
}
public synchronized Optional<Integer> getMsn(MessageUid uid) {
http://git-wip-us.apache.org/repos/asf/james-project/blob/53d75365/protocols/imap/src/test/java/org/apache/james/imap/processor/base/SelectedMailboxImplTest.java
----------------------------------------------------------------------
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/base/SelectedMailboxImplTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/base/SelectedMailboxImplTest.java
index a9e7144..cdeef78 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/base/SelectedMailboxImplTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/base/SelectedMailboxImplTest.java
@@ -52,7 +52,6 @@ import org.apache.james.mailbox.store.mail.model.DefaultMessageId;
import org.apache.james.mailbox.store.mail.model.Mailbox;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -65,7 +64,9 @@ import com.google.common.collect.ImmutableList;
public class SelectedMailboxImplTest {
private static final Logger LOGGER = LoggerFactory.getLogger(SelectedMailboxImplTest.class);
- public static final MessageUid MESSAGE_UID_5 = MessageUid.of(5);
+ private static final MessageUid EMITTED_EVENT_UID = MessageUid.of(5);
+ private static final int MOD_SEQ = 12;
+ private static final int SIZE = 38;
private ExecutorService executorService;
private MailboxManager mailboxManager;
@@ -77,20 +78,23 @@ public class SelectedMailboxImplTest {
@Before
public void setUp() throws Exception {
executorService = Executors.newFixedThreadPool(1);
-
mailboxPath = new MailboxPath(MailboxConstants.USER_NAMESPACE, "tellier@linagora.com", MailboxConstants.INBOX);
mailboxManager = mock(MailboxManager.class);
messageManager = mock(MessageManager.class);
- when(mailboxManager.getMailbox(eq(mailboxPath), any(MailboxSession.class))).thenReturn(messageManager);
- when(messageManager.getApplicableFlags(any(MailboxSession.class))).thenReturn(new Flags());
+ imapSession = mock(ImapSession.class);
+ mailbox = mock(Mailbox.class);
+
+ when(mailboxManager.getMailbox(eq(mailboxPath), any(MailboxSession.class)))
+ .thenReturn(messageManager);
+ when(messageManager.getApplicableFlags(any(MailboxSession.class)))
+ .thenReturn(new Flags());
when(messageManager.search(any(SearchQuery.class), any(MailboxSession.class)))
- .then(sleepThenSearchAnswer());
+ .then(delayedSearchAnswer());
- imapSession = mock(ImapSession.class);
when(imapSession.getAttribute(ImapSessionUtils.MAILBOX_SESSION_ATTRIBUTE_SESSION_KEY)).thenReturn(mock(MailboxSession.class));
- mailbox = mock(Mailbox.class);
- when(mailbox.generateAssociatedPath()).thenReturn(mailboxPath);
+ when(mailbox.generateAssociatedPath())
+ .thenReturn(mailboxPath);
}
@After
@@ -98,11 +102,10 @@ public class SelectedMailboxImplTest {
executorService.shutdownNow();
}
- @Ignore
@Test
- public void concurrentEventShouldNotSkipUidEmmitedDuringInitialization() throws Exception {
- final AtomicInteger success = new AtomicInteger(0);
- doAnswer(generateEmitEventAnswer(success))
+ public void concurrentEventShouldNotSkipAddedEventsEmittedDuringInitialisation() throws Exception {
+ final AtomicInteger successCount = new AtomicInteger(0);
+ doAnswer(generateEmitEventAnswer(successCount))
.when(mailboxManager)
.addListener(eq(mailboxPath), any(MailboxListener.class), any(MailboxSession.class));
@@ -111,14 +114,13 @@ public class SelectedMailboxImplTest {
imapSession,
mailboxPath);
- assertThat(selectedMailbox.getLastUid().get()).isEqualTo(MESSAGE_UID_5);
+ assertThat(selectedMailbox.getLastUid().get()).isEqualTo(EMITTED_EVENT_UID);
}
- @Ignore
@Test
- public void concurrentEventShouldBeSupportedDuringInitialisation() throws Exception {
- final AtomicInteger success = new AtomicInteger(0);
- doAnswer(generateEmitEventAnswer(success))
+ public void concurrentEventShouldBeProcessedSuccessfullyDuringInitialisation() throws Exception {
+ final AtomicInteger successCount = new AtomicInteger(0);
+ doAnswer(generateEmitEventAnswer(successCount))
.when(mailboxManager)
.addListener(eq(mailboxPath), any(MailboxListener.class), any(MailboxSession.class));
@@ -127,12 +129,12 @@ public class SelectedMailboxImplTest {
imapSession,
mailboxPath);
- assertThat(success.get())
+ assertThat(successCount.get())
.as("Get the incremented value in case of successful event processing.")
.isEqualTo(1);
}
- private Answer<Iterator<MessageUid>> sleepThenSearchAnswer() {
+ private Answer<Iterator<MessageUid>> delayedSearchAnswer() {
return new Answer<Iterator<MessageUid>>() {
@Override
public Iterator<MessageUid> answer(InvocationOnMock invocation) throws Throwable {
@@ -166,7 +168,7 @@ public class SelectedMailboxImplTest {
private void emitEvent(MailboxListener mailboxListener) {
TreeMap<MessageUid, MessageMetaData> result = new TreeMap<MessageUid, MessageMetaData>();
- result.put(MESSAGE_UID_5, new SimpleMessageMetaData(MESSAGE_UID_5, 12, new Flags(), 38, new Date(), new DefaultMessageId()));
+ result.put(EMITTED_EVENT_UID, new SimpleMessageMetaData(EMITTED_EVENT_UID, MOD_SEQ, new Flags(), SIZE, new Date(), new DefaultMessageId()));
mailboxListener.event(new EventFactory().added(mock(MailboxSession.class), result, mailbox));
}
}
http://git-wip-us.apache.org/repos/asf/james-project/blob/53d75365/protocols/imap/src/test/java/org/apache/james/imap/processor/base/UidMsnConverterTest.java
----------------------------------------------------------------------
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/base/UidMsnConverterTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/base/UidMsnConverterTest.java
index 4606e83..ae81f2b 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/processor/base/UidMsnConverterTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/base/UidMsnConverterTest.java
@@ -42,7 +42,7 @@ public class UidMsnConverterTest {
@Before
public void setUp() {
- testee = new UidMsnConverter(ImmutableList.<MessageUid>of().iterator());
+ testee = new UidMsnConverter();
messageUid1 = MessageUid.of(1);
messageUid2 = MessageUid.of(2);
messageUid3 = MessageUid.of(3);
@@ -178,7 +178,7 @@ public class UidMsnConverterTest {
}
@Test
- public void removeShouldKeepAValidMappingWhenDeletingBeginning() {
+ public void removeShouldKeepAMonoticMSNToUIDConversionMappingWhenDeletingBeginning() {
testee.addUid(messageUid1);
testee.addUid(messageUid2);
testee.addUid(messageUid3);
@@ -194,7 +194,7 @@ public class UidMsnConverterTest {
}
@Test
- public void removeShouldKeepAValidMappingWhenDeletingEnd() {
+ public void removeShouldKeepAMonoticMSNToUIDConversionMappingWhenDeletingEnd() {
testee.addUid(messageUid1);
testee.addUid(messageUid2);
testee.addUid(messageUid3);
@@ -210,7 +210,7 @@ public class UidMsnConverterTest {
}
@Test
- public void removeShouldKeepAValidMappingWhenDeletingMiddle() {
+ public void removeShouldKeepAMonoticMSNToUIDConversionMappingWhenDeletingMiddle() {
testee.addUid(messageUid1);
testee.addUid(messageUid2);
testee.addUid(messageUid3);
@@ -233,7 +233,7 @@ public class UidMsnConverterTest {
testee.addUid(messageUid4);
assertThat(mapTesteeInternalDataToMsnByUid().entrySet())
- .containsOnlyElementsOf(ImmutableMap.of(
+ .containsExactlyElementsOf(ImmutableMap.of(
1, messageUid1,
2, messageUid2,
3, messageUid3,
@@ -241,14 +241,14 @@ public class UidMsnConverterTest {
}
@Test
- public void addUidShouldLeadToValidConversionWhenInsertInFirstPosition() {
+ public void addUidShouldLeadToMonoticMSNToUIDConversionWhenInsertInFirstPosition() {
testee.addUid(messageUid2);
testee.addUid(messageUid3);
testee.addUid(messageUid4);
testee.addUid(messageUid1);
assertThat(mapTesteeInternalDataToMsnByUid().entrySet())
- .containsOnlyElementsOf(ImmutableMap.of(
+ .containsExactlyElementsOf(ImmutableMap.of(
1, messageUid1,
2, messageUid2,
3, messageUid3,
@@ -256,15 +256,99 @@ public class UidMsnConverterTest {
}
@Test
- public void constructorWithOutOfOrderIteratorShouldLeadToValidConversion() {
- testee = new UidMsnConverter(ImmutableList.of(messageUid2,
+ public void addAllShouldLeadToMonoticMSNToUIDConversion() {
+ testee.addAll(ImmutableList.of(
+ messageUid1,
+ messageUid2,
+ messageUid3,
+ messageUid4));
+
+ assertThat(mapTesteeInternalDataToMsnByUid().entrySet())
+ .containsExactlyElementsOf(ImmutableMap.of(
+ 1, messageUid1,
+ 2, messageUid2,
+ 3, messageUid3,
+ 4, messageUid4).entrySet());
+ }
+
+ @Test
+ public void addAllShouldRemoveDuplicates() {
+ testee.addAll(ImmutableList.of(
+ messageUid1,
+ messageUid2,
+ messageUid2,
+ messageUid3,
+ messageUid4));
+
+ assertThat(mapTesteeInternalDataToMsnByUid().entrySet())
+ .containsExactlyElementsOf(ImmutableMap.of(
+ 1, messageUid1,
+ 2, messageUid2,
+ 3, messageUid3,
+ 4, messageUid4).entrySet());
+ }
+
+ @Test
+ public void addAllShouldDeduplicateElements() {
+ testee.addUid(messageUid1);
+
+ testee.addAll(ImmutableList.of(
+ messageUid1,
+ messageUid2,
+ messageUid3,
+ messageUid4));
+
+ assertThat(mapTesteeInternalDataToMsnByUid().entrySet())
+ .containsExactlyElementsOf(ImmutableMap.of(
+ 1, messageUid1,
+ 2, messageUid2,
+ 3, messageUid3,
+ 4, messageUid4).entrySet());
+ }
+
+ @Test
+ public void addAllShouldMergeWithPreviousData() {
+ testee.addUid(messageUid1);
+
+ testee.addAll(ImmutableList.of(messageUid2,
+ messageUid3,
+ messageUid4));
+
+ assertThat(mapTesteeInternalDataToMsnByUid().entrySet())
+ .containsExactlyElementsOf(ImmutableMap.of(
+ 1, messageUid1,
+ 2, messageUid2,
+ 3, messageUid3,
+ 4, messageUid4).entrySet());
+ }
+
+ @Test
+ public void addAllShouldMergeAndDeduplicatePreviousData() {
+ testee.addUid(messageUid1);
+ testee.addUid(messageUid3);
+
+ testee.addAll(ImmutableList.of(messageUid2,
+ messageUid3,
+ messageUid4));
+
+ assertThat(mapTesteeInternalDataToMsnByUid().entrySet())
+ .containsExactlyElementsOf(ImmutableMap.of(
+ 1, messageUid1,
+ 2, messageUid2,
+ 3, messageUid3,
+ 4, messageUid4).entrySet());
+ }
+
+ @Test
+ public void addAllWithOutOfOrderIteratorShouldLeadToMonoticMSNToUIDConversion() {
+ testee.addAll(ImmutableList.of(
+ messageUid2,
messageUid3,
messageUid4,
- messageUid1)
- .iterator());
+ messageUid1));
assertThat(mapTesteeInternalDataToMsnByUid().entrySet())
- .containsOnlyElementsOf(ImmutableMap.of(
+ .containsExactlyElementsOf(ImmutableMap.of(
1, messageUid1,
2, messageUid2,
3, messageUid3,
@@ -281,7 +365,7 @@ public class UidMsnConverterTest {
}
@Test
- public void addAndRemoveShouldLeadToValidConversionWhenMixed() throws Exception {
+ public void addAndRemoveShouldLeadToMonoticMSNToUIDConversionWhenMixed() throws Exception {
final int initialCount = 1000;
for (int i = 1; i <= initialCount; i++) {
testee.addUid(MessageUid.of(i));
@@ -307,11 +391,11 @@ public class UidMsnConverterTest {
resultBuilder.put(i, MessageUid.of(initialCount + i));
}
assertThat(mapTesteeInternalDataToMsnByUid().entrySet())
- .containsOnlyElementsOf(resultBuilder.build().entrySet());
+ .containsExactlyElementsOf(resultBuilder.build().entrySet());
}
@Test
- public void addShouldLeadToValidConversionWhenConcurrent() throws Exception {
+ public void addShouldLeadToMonoticMSNToUIDConversionWhenConcurrent() throws Exception {
final int operationCount = 1000;
int threadCount = 2;
@@ -330,11 +414,11 @@ public class UidMsnConverterTest {
resultBuilder.put(i, MessageUid.of(i));
}
assertThat(mapTesteeInternalDataToMsnByUid().entrySet())
- .containsOnlyElementsOf(resultBuilder.build().entrySet());
+ .containsExactlyElementsOf(resultBuilder.build().entrySet());
}
@Test
- public void removeShouldLeadToValidConversionWhenConcurrent() throws Exception {
+ public void removeShouldLeadToMonoticMSNToUIDConversionWhenConcurrent() throws Exception {
final int operationCount = 1000;
int threadCount = 2;
for (int i = 1; i <= operationCount * (threadCount + 1); i++) {
@@ -356,7 +440,7 @@ public class UidMsnConverterTest {
resultBuilder.put(i, MessageUid.of((threadCount * operationCount) + i));
}
assertThat(mapTesteeInternalDataToMsnByUid().entrySet())
- .containsOnlyElementsOf(resultBuilder.build().entrySet());
+ .containsExactlyElementsOf(resultBuilder.build().entrySet());
}
private Map<Integer, MessageUid> mapTesteeInternalDataToMsnByUid() {
http://git-wip-us.apache.org/repos/asf/james-project/blob/53d75365/protocols/imap/src/test/resources/logback-test.xml
----------------------------------------------------------------------
diff --git a/protocols/imap/src/test/resources/logback-test.xml b/protocols/imap/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..5e4c459
--- /dev/null
+++ b/protocols/imap/src/test/resources/logback-test.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+
+ <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
+ <resetJUL>true</resetJUL>
+ </contextListener>
+
+ <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>%d{HH:mm:ss.SSS} %highlight([%-5level]) %logger{15} - %msg%n%rEx</pattern>
+ <immediateFlush>false</immediateFlush>
+ </encoder>
+ </appender>
+
+ <root level="ERROR">
+ <appender-ref ref="CONSOLE" />
+ </root>
+
+
+ <logger name="org.apache.james" level="DEBUG" >
+ <appender-ref ref="CONSOLE" />
+ </logger>
+
+</configuration>
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org