JAMES-2290 try to make MemoryMailRepository to break with parallelism (fail)
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/a0d734f9 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/a0d734f9 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/a0d734f9 Branch: refs/heads/master Commit: a0d734f95a12050c627bd6f1f3ad9f068c958f6e Parents: cba5a2f Author: Matthieu Baechler <matth...@apache.org> Authored: Wed Jan 17 17:09:45 2018 +0100 Committer: benwa <btell...@linagora.com> Committed: Fri Jan 19 18:57:58 2018 +0700 ---------------------------------------------------------------------- .../mailrepository/mailrepository-api/pom.xml | 5 ++ .../mailrepository/MailRepositoryContract.java | 63 ++++++++++++++++++++ .../mailrepository-memory/pom.xml | 5 ++ 3 files changed, 73 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/a0d734f9/server/mailrepository/mailrepository-api/pom.xml ---------------------------------------------------------------------- diff --git a/server/mailrepository/mailrepository-api/pom.xml b/server/mailrepository/mailrepository-api/pom.xml index b2fc1e7..26e97ec 100644 --- a/server/mailrepository/mailrepository-api/pom.xml +++ b/server/mailrepository/mailrepository-api/pom.xml @@ -43,6 +43,11 @@ <scope>test</scope> </dependency> <dependency> + <groupId>org.apache.james</groupId> + <artifactId>james-server-testing</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <scope>test</scope> http://git-wip-us.apache.org/repos/asf/james-project/blob/a0d734f9/server/mailrepository/mailrepository-api/src/test/java/org/apache/james/mailrepository/MailRepositoryContract.java ---------------------------------------------------------------------- diff --git a/server/mailrepository/mailrepository-api/src/test/java/org/apache/james/mailrepository/MailRepositoryContract.java b/server/mailrepository/mailrepository-api/src/test/java/org/apache/james/mailrepository/MailRepositoryContract.java index 2afdf76..f89eb14 100644 --- a/server/mailrepository/mailrepository-api/src/test/java/org/apache/james/mailrepository/MailRepositoryContract.java +++ b/server/mailrepository/mailrepository-api/src/test/java/org/apache/james/mailrepository/MailRepositoryContract.java @@ -24,7 +24,13 @@ import static org.junit.jupiter.api.Assertions.assertAll; import java.nio.charset.StandardCharsets; import java.util.Date; +import java.util.Iterator; import java.util.List; +import java.util.Random; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; +import java.util.stream.IntStream; import javax.mail.MessagingException; import javax.mail.internet.MimeMessage; @@ -33,10 +39,16 @@ import org.apache.james.core.MailAddress; import org.apache.james.core.builder.MimeMessageBuilder; import org.apache.james.mailrepository.api.MailRepository; import org.apache.james.server.core.MailImpl; +import org.apache.james.util.concurrency.ConcurrentTestRunner; +import org.apache.james.utils.DiscreteDistribution; +import org.apache.james.utils.DiscreteDistribution.DistributionEntry; import org.apache.mailet.Mail; import org.apache.mailet.PerRecipientHeaders; +import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; +import com.github.fge.lambdas.runnable.ThrowingRunnable; +import com.github.steveash.guavate.Guavate; import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.hash.Hashing; @@ -304,4 +316,55 @@ public interface MailRepositoryContract { assertThat(testee.retrieve(key)).satisfies(actual -> checkMailEquality(actual, mail)); } + @RepeatedTest(100) + default void storingAndRemovingMessagesConcurrentlyShouldLeadToConsistentResult() throws Exception { + MailRepository testee = retrieveRepository(); + int nbKeys = 20; + int nbIterations = 10; + int threadCount = 10; + ConcurrentHashMap.KeySetView<String, Boolean> expectedResult = ConcurrentHashMap.newKeySet(); + List<Object> locks = IntStream.range(0, 10) + .boxed() + .collect(Guavate.toImmutableList()); + + Random random = new Random(); + ThrowingRunnable add = () -> { + int keyIndex = computeKeyIndex(nbKeys, random.nextInt()); + String key = computeKey(keyIndex); + synchronized (locks.get(keyIndex)) { + testee.store(createMail(key)); + expectedResult.add(key); + } + }; + + ThrowingRunnable remove = () -> { + int keyIndex = computeKeyIndex(nbKeys, random.nextInt()); + String key = computeKey(keyIndex); + synchronized (locks.get(keyIndex)) { + testee.remove(key); + expectedResult.remove(key); + } + }; + + DiscreteDistribution<ThrowingRunnable> distribution = DiscreteDistribution.create( + ImmutableList.of( + new DistributionEntry<>(add, 0.25), + new DistributionEntry<>(remove, 0.75))); + + new ConcurrentTestRunner(threadCount, nbIterations, + (a, b) -> distribution.sample().run()) + .run() + .awaitTermination(1, TimeUnit.MINUTES); + + assertThat(testee.list()).containsOnlyElementsOf(expectedResult); + } + + default String computeKey(int keyIndex) { + return "mail" + keyIndex; + } + + default int computeKeyIndex(int nbKeys, Integer i) { + return i % nbKeys; + } + } http://git-wip-us.apache.org/repos/asf/james-project/blob/a0d734f9/server/mailrepository/mailrepository-memory/pom.xml ---------------------------------------------------------------------- diff --git a/server/mailrepository/mailrepository-memory/pom.xml b/server/mailrepository/mailrepository-memory/pom.xml index 4870dc5..0fec615 100644 --- a/server/mailrepository/mailrepository-memory/pom.xml +++ b/server/mailrepository/mailrepository-memory/pom.xml @@ -38,6 +38,11 @@ <artifactId>james-server-core</artifactId> </dependency> <dependency> + <groupId>org.apache.james</groupId> + <artifactId>james-server-testing</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>${project.groupId}</groupId> <artifactId>james-server-mailrepository-api</artifactId> </dependency> --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org