package mireka.transmission.immediate.direct; import static mireka.ExampleAddress.*; import static org.junit.Assert.*; import java.net.InetAddress; import java.util.Arrays; import mireka.ExampleMail; import mireka.address.Domain; import mireka.address.Recipient; import mireka.smtp.EnhancedStatus; import mireka.smtp.SendException; import mireka.smtp.client.ClientFactory; import mireka.smtp.client.MtaAddress; import mireka.smtp.client.SmtpClient; import mireka.transmission.Mail; import mireka.transmission.immediate.DirectImmediateSender; import mireka.transmission.immediate.PostponeException; import mireka.transmission.immediate.RecipientsWereRejectedException; import mireka.transmission.immediate.dns.AddressLookup; import mireka.transmission.immediate.dns.MxLookup; import mireka.transmission.immediate.host.MailToHostTransmitter; import mockit.Expectations; import mockit.Injectable; import mockit.Mocked; import mockit.NonStrictExpectations; import mockit.Tested; import mockit.Verifications; import org.junit.Before; import org.junit.Test; import org.xbill.DNS.Name; public class DirectImmediateSenderTest { @Tested private DirectImmediateSender sender; /** Automatically created by constructor, cannot be @Injected **/ @Mocked private MxLookup mxLookup; /** Automatically created by constructor, cannot be @Injected **/ @Mocked private AddressLookup addressLookup; @Injectable private ClientFactory clientFactory; @Mocked private SmtpClient client; @Injectable private MailToHostTransmitter mailToHostTransmitter; private final Mail mail = ExampleMail.simple(); private Mail adaAddressLiteralMail; private Mail janeJoeMail; private final SendException permanentSendException = new SendException( "Example permanent failure", EnhancedStatus.PERMANENT_UNABLE_TO_ROUTE); private final SendException transientSendException = new SendException( "Example transient failure", EnhancedStatus.TRANSIENT_LOCAL_ERROR_IN_PROCESSING); private static final PostponeException POSTPONE_EXCEPTION = new PostponeException( 10, EnhancedStatus.TRANSIENT_SYSTEM_NOT_ACCEPTING_NETWORK_MESSAGES, "Test exception"); @Before public void initialize() { adaAddressLiteralMail = ExampleMail.simple(); adaAddressLiteralMail.recipients = Arrays.asList(ADA_ADDRESS_LITERAL_AS_RECIPIENT); janeJoeMail = ExampleMail.simple(); janeJoeMail.recipients = Arrays.asList(JANE_AS_RECIPIENT, JOHN_AS_RECIPIENT); new NonStrictExpectations() { { clientFactory.create(); result = client; } }; } @Test public void testSendToAddressLiteralVerifyNoDns() throws SendException, RecipientsWereRejectedException, PostponeException { sender.send(adaAddressLiteralMail); new Verifications() { { mxLookup.queryMxTargets((Domain)any); times = 0; addressLookup.queryAddresses((Name)any); times = 0; mailToHostTransmitter.transmit((Mail) any, null); client.setMtaAddress(new MtaAddress(ADDRESS_LITERAL, IP)); } }; } @Test public void testSendToDomain() throws SendException, RecipientsWereRejectedException, PostponeException { new Expectations() { { mxLookup.queryMxTargets((Domain)any); result = new Name[] { HOST1_EXAMPLE_COM_NAME }; addressLookup.queryAddresses((Name)any); result = new InetAddress[] { IP_ADDRESS_ONLY }; client.setMtaAddress(new MtaAddress("host1.example.com", IP)); mailToHostTransmitter.transmit((Mail) any, null); } }; sender.send(mail); } @Test(expected = IllegalArgumentException.class) public void testSendToDifferentDomain() throws SendException, RecipientsWereRejectedException, PostponeException { mail.recipients = Arrays.asList(JANE_AS_RECIPIENT, NANCY_NET_AS_RECIPIENT); sender.send(mail); } @Test(expected = IllegalArgumentException.class) public void testSendToGlobalPostmaster() throws SendException, RecipientsWereRejectedException, PostponeException { mail.recipients = Arrays.asList((Recipient) GLOBAL_POSTMASTER_AS_RECIPIENT); sender.send(mail); } @Test public void testSendFirstMxCannotBeResolved() throws SendException, RecipientsWereRejectedException, PostponeException { new Expectations() { { mxLookup.queryMxTargets((Domain)any); result = new Name[] { HOST1_EXAMPLE_COM_NAME, HOST2_EXAMPLE_COM_NAME }; addressLookup.queryAddresses((Name)any); result = permanentSendException; result = new InetAddress[] { IP2 }; client.setMtaAddress(new MtaAddress("host2.example.com", IP2)); mailToHostTransmitter.transmit((Mail) any, null); } }; sender.send(mail); } @Test public void testSendFirstHostHasTransientProblem() throws SendException, RecipientsWereRejectedException, PostponeException { twoMxDnsExpectation(); new Expectations() { { mailToHostTransmitter.transmit((Mail) any, null); result = transientSendException; mailToHostTransmitter.transmit((Mail) any, null); result = null; } }; sender.send(mail); } private void twoMxDnsExpectation() throws SendException { new NonStrictExpectations() { { mxLookup.queryMxTargets((Domain)any); result = new Name[] { HOST1_EXAMPLE_COM_NAME, HOST2_EXAMPLE_COM_NAME }; times = 1; addressLookup.queryAddresses((Name)any); result = new InetAddress[] { IP1 }; result = new InetAddress[] { IP2 }; times = 2; } }; } @Test(expected = SendException.class) public void testSendFirstHostHasPermanentProblem() throws SendException, RecipientsWereRejectedException, PostponeException { new Expectations() { { mxLookup.queryMxTargets((Domain)any); result = new Name[] { HOST1_EXAMPLE_COM_NAME, HOST2_EXAMPLE_COM_NAME }; addressLookup.queryAddresses((Name)any); result = new InetAddress[] { IP1 }; mailToHostTransmitter.transmit((Mail) any, null); result = permanentSendException; } }; sender.send(mail); } @Test public void testSendFirstHostHasTransientSecondHasPermanentProblem() throws SendException, RecipientsWereRejectedException, PostponeException { twoMxDnsExpectation(); new Expectations() { { mailToHostTransmitter.transmit((Mail) any, null); result = transientSendException; mailToHostTransmitter.transmit((Mail) any, null); result = permanentSendException; } }; try { sender.send(mail); fail("Exception expected"); } catch (SendException e) { assertFalse(e.errorStatus().shouldRetry()); } } @Test public void testSendFirstHostPostponed() throws SendException, RecipientsWereRejectedException, PostponeException { twoMxDnsExpectation(); new Expectations() { { mailToHostTransmitter.transmit((Mail) any, null); result = POSTPONE_EXCEPTION; mailToHostTransmitter.transmit((Mail) any, null); result = null; } }; sender.send(mail); } @Test public void testSendFirstHostPostponedSecondHasTransientProblem() throws SendException, RecipientsWereRejectedException, PostponeException { twoMxDnsExpectation(); new Expectations() { { mailToHostTransmitter.transmit((Mail) any, null); result = POSTPONE_EXCEPTION; mailToHostTransmitter.transmit((Mail) any, null); result = transientSendException; } }; try { sender.send(mail); fail("Exception expected"); } catch (SendException e) { assertTrue(e.errorStatus().shouldRetry()); } } @Test(expected = PostponeException.class) public void testSendBothPostponed() throws SendException, RecipientsWereRejectedException, PostponeException { twoMxDnsExpectation(); new Expectations() { { mailToHostTransmitter.transmit((Mail) any, null); result = POSTPONE_EXCEPTION; mailToHostTransmitter.transmit((Mail) any, null); result = POSTPONE_EXCEPTION; } }; sender.send(mail); } @Test public void testSendSingleHostPermanentlyCannotBeResolved() throws SendException, RecipientsWereRejectedException, PostponeException { new Expectations() { { mxLookup.queryMxTargets((Domain)any); result = new Name[] { HOST1_EXAMPLE_COM_NAME }; addressLookup.queryAddresses((Name)any); result = permanentSendException; } }; try { sender.send(mail); fail("An exception must have been thrown"); } catch (SendException e) { assertFalse(e.errorStatus().shouldRetry()); } } @Test public void testSendSingleHostTemporarilyCannotBeResolved() throws SendException, RecipientsWereRejectedException, PostponeException { new Expectations() { { mxLookup.queryMxTargets((Domain)any); result = new Name[] { HOST1_EXAMPLE_COM_NAME }; addressLookup.queryAddresses((Name)any); result = transientSendException; } }; try { sender.send(mail); fail("An exception must have been thrown"); } catch (SendException e) { assertTrue(e.errorStatus().shouldRetry()); } } @Test(expected = PostponeException.class) public void testSendSingleHostPostponeException() throws SendException, RecipientsWereRejectedException, PostponeException { new Expectations() { { mxLookup.queryMxTargets((Domain)any); result = new Name[] { HOST1_EXAMPLE_COM_NAME }; addressLookup.queryAddresses((Name)any); result = new InetAddress[] { IP1 }; mailToHostTransmitter.transmit((Mail) any, null); result = POSTPONE_EXCEPTION; } }; sender.send(mail); } }