Java tutorial
/* * Copyright (C) 2000 - 2018 Silverpeas * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * As a special exception to the terms and conditions of version 3.0 of * the GPL, you may redistribute this Program in connection with Free/Libre * Open Source Software ("FLOSS") applications as described in Silverpeas's * FLOSS exception. You should have received a copy of the text describing * the FLOSS exception, and it is also available here: * "https://www.silverpeas.org/legal/floss_exception.html" * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package org.silverpeas.core.mail; import com.icegreen.greenmail.base.GreenMailOperations; import org.apache.commons.lang3.reflect.FieldUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.parallel.Execution; import org.junit.jupiter.api.parallel.ExecutionMode; import org.silverpeas.core.mail.engine.MailSender; import org.silverpeas.core.mail.engine.MailSenderProvider; import org.silverpeas.core.mail.engine.MailSenderTask; import org.silverpeas.core.mail.engine.SmtpMailSender; import org.silverpeas.core.test.extention.GreenMailExtension; import org.silverpeas.core.test.extention.LoggerExtension; import org.silverpeas.core.test.extention.LoggerLevel; import org.silverpeas.core.test.extention.EnableSilverTestEnv; import org.silverpeas.core.test.extention.SmtpConfig; import org.silverpeas.core.test.extention.TestManagedBeans; import org.silverpeas.core.util.StringUtil; import org.silverpeas.core.util.logging.Level; import javax.mail.internet.MimeMessage; import java.util.ArrayList; import java.util.List; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; @EnableSilverTestEnv @ExtendWith(LoggerExtension.class) @ExtendWith(GreenMailExtension.class) @LoggerLevel(Level.DEBUG) @SmtpConfig("/org/silverpeas/notificationserver/channel/smtp/smtpSettings.properties") @Execution(ExecutionMode.SAME_THREAD) @TestManagedBeans(MailSenderTask.class) public class SmtpMailSendingMassiveTest { private final static String COMMON_FROM = "from@titi.org"; private final static String COMMON_TO = "to@toto.org"; private MailSender oldMailSender; private long lastLogTime = -1; @BeforeEach public void setup() throws Exception { // Injecting by reflection the mock instance oldMailSender = MailSenderProvider.get(); FieldUtils.writeDeclaredStaticField(MailSenderProvider.class, "mailSender", new StubbedSmtpMailSender(), true); } @AfterEach public void destroy() throws Exception { // Replacing by reflection the mock instances by the previous extracted one. FieldUtils.writeDeclaredStaticField(MailSenderProvider.class, "mailSender", oldMailSender, true); } @Test public void sendingSeveralMailsSynchronouslyAndAsynchronouslyAndVerifyingSendingPerformedOneByOne( GreenMailOperations mail) throws Exception { List<Runnable> runnables = new ArrayList<>(); List<Thread> threads = new ArrayList<>(); for (int i = 0; i < 100; i++) { Runnable runnable = new SendOperation("ID_" + StringUtil.leftPad(String.valueOf(i), 3, "0"), (i % 4 != 0)); runnables.add(runnable); threads.add(new Thread(runnable)); } log("STARTING THREADS..."); // Starting threads for (Thread thread : threads) { Thread.sleep(50); thread.start(); } log(runnables.size() + " THREADS STARTED"); log("WAITING ENDING OF THREADS..."); // Waiting for the end of all threads. for (Thread thread : threads) { thread.join(60000); } log(runnables.size() + " THREADS STOPPED"); // Verifying that mails has been sent mail.waitForIncomingEmail(60000, runnables.size()); Thread.sleep(100); assertMailSentOneByOne(runnables); MimeMessage[] messages = mail.getReceivedMessages(); assertThat(messages, arrayWithSize(runnables.size())); System.out.println("Received messages:"); for (MimeMessage message : messages) { System.out.println("\t" + message.getSubject()); } } private class SendOperation implements Runnable { private final String id; private final boolean asynch; private SendOperation(final String id, final boolean asynch) { this.id = id; this.asynch = asynch; } @Override public void run() { MailAddress senderEmail = MailAddress.eMail(COMMON_FROM); MailAddress receiverEmail = MailAddress.eMail(COMMON_TO); MailSending mailSending = MailSending.from(senderEmail).to(receiverEmail) .withSubject(id + " subject - " + (asynch ? "A" : "S")).withContent(id + " content"); // Sending mail if (asynch) { log(id + " - send asynchronously..."); mailSending.send(); } else { log(id + " - send synchronously..."); mailSending.sendSynchronously(); } } } /* Tool methods */ private synchronized void log(String message) { long currentTime = System.currentTimeMillis(); if (lastLogTime < 0) { lastLogTime = currentTime; } System.out.println( StringUtil.leftPad(String.valueOf(currentTime - lastLogTime), 6, " ") + " ms -> " + message); } private void assertMailSentOneByOne(List<Runnable> runnables) { List<String> mailSentOneByOne = getStubbedSmtpMailSender().sentOneByOne; assertThat(mailSentOneByOne.size() % 2, is(0)); assertThat(mailSentOneByOne, hasSize(runnables.size() * 2)); for (int i = 0; i < mailSentOneByOne.size(); i = i + 2) { assertThat(mailSentOneByOne.get(i), is("TIC")); assertThat(mailSentOneByOne.get(i + 1), is("TAC")); } } private StubbedSmtpMailSender getStubbedSmtpMailSender() { return (StubbedSmtpMailSender) MailSenderProvider.get(); } /** * Stubbed SMTP mail sender. */ class StubbedSmtpMailSender extends SmtpMailSender { public List<String> sentOneByOne = new ArrayList<>(); @Override public void send(final MailToSend mail) { try { Thread.sleep(5); } catch (InterruptedException ignored) { } tagOneByOne("TIC"); log(mail.getSubject() + " - " + (mail.isAsynchronous() ? "asynchronously" : "synchronously") + " - sending..."); super.send(mail); log(mail.getSubject() + " - sent."); tagOneByOne("TAC"); } private synchronized void tagOneByOne(String tag) { sentOneByOne.add(tag); } } }