package com.hubspot.smtp.client; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.*; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.function.Supplier; import org.assertj.core.util.Lists; import org.junit.Test; import io.netty.handler.codec.smtp.DefaultSmtpRequest; import io.netty.handler.codec.smtp.DefaultSmtpResponse; import io.netty.handler.codec.smtp.SmtpCommand; import io.netty.handler.codec.smtp.SmtpRequest; import io.netty.handler.codec.smtp.SmtpResponse; public class CompositeSendInterceptorTest { private static final DefaultSmtpRequest MAIL_REQUEST = new DefaultSmtpRequest(SmtpCommand.MAIL); private static final List<SmtpResponse> DEFAULT_RESPONSE = Lists.newArrayList(new DefaultSmtpResponse(250, "OK")); private static final SendInterceptor RESPONSE_SEND_INTERCEPTOR = new SendInterceptor() { @Override public CompletableFuture<List<SmtpResponse>> aroundRequest(SmtpRequest request, Supplier<CompletableFuture<List<SmtpResponse>>> next) { return CompletableFuture.completedFuture(DEFAULT_RESPONSE); } @Override public CompletableFuture<List<SmtpResponse>> aroundData(Supplier<CompletableFuture<List<SmtpResponse>>> next) { return CompletableFuture.completedFuture(DEFAULT_RESPONSE); } @Override public CompletableFuture<List<SmtpResponse>> aroundPipelinedSequence(List<SmtpRequest> requests, Supplier<CompletableFuture<List<SmtpResponse>>> next) { return CompletableFuture.completedFuture(DEFAULT_RESPONSE); } }; private static final SendInterceptor ALWAYS_FAILS_SEND_INTERCEPTOR = new SendInterceptor() { @Override public CompletableFuture<List<SmtpResponse>> aroundRequest(SmtpRequest request, Supplier<CompletableFuture<List<SmtpResponse>>> next) { return getFailedFuture(); } @Override public CompletableFuture<List<SmtpResponse>> aroundData(Supplier<CompletableFuture<List<SmtpResponse>>> next) { return getFailedFuture(); } @Override public CompletableFuture<List<SmtpResponse>> aroundPipelinedSequence(List<SmtpRequest> requests, Supplier<CompletableFuture<List<SmtpResponse>>> next) { return getFailedFuture(); } private CompletableFuture<List<SmtpResponse>> getFailedFuture() { CompletableFuture<List<SmtpResponse>> future = new CompletableFuture<>(); future.completeExceptionally(new Exception("fail")); return future; } }; private static final SendInterceptor PASS_THROUGH_SEND_INTERCEPTOR = new SendInterceptor() { @Override public CompletableFuture<List<SmtpResponse>> aroundRequest(SmtpRequest request, Supplier<CompletableFuture<List<SmtpResponse>>> next) { return next.get(); } @Override public CompletableFuture<List<SmtpResponse>> aroundData(Supplier<CompletableFuture<List<SmtpResponse>>> next) { return next.get(); } @Override public CompletableFuture<List<SmtpResponse>> aroundPipelinedSequence(List<SmtpRequest> requests, Supplier<CompletableFuture<List<SmtpResponse>>> next) { return next.get(); } }; @Test public void itWrapsInterceptors() throws Exception { List<SmtpResponse> responses = CompositeSendInterceptor.of(RESPONSE_SEND_INTERCEPTOR).aroundRequest(MAIL_REQUEST, null).get(); assertThat(responses).isEqualTo(DEFAULT_RESPONSE); } @Test public void itOrdersInterceptors() throws Exception { List<SmtpResponse> responses = CompositeSendInterceptor.of(PASS_THROUGH_SEND_INTERCEPTOR, RESPONSE_SEND_INTERCEPTOR).aroundRequest(MAIL_REQUEST, null).get(); assertThat(responses).isEqualTo(DEFAULT_RESPONSE); } @Test public void itExecutesInterceptorsLazily() throws Exception { SendInterceptor mockSendInterceptor = mock(SendInterceptor.class); CompletableFuture<List<SmtpResponse>> future = CompositeSendInterceptor.of(ALWAYS_FAILS_SEND_INTERCEPTOR, mockSendInterceptor).aroundRequest(MAIL_REQUEST, null); assertThat(future.isCompletedExceptionally()).isTrue(); verify(mockSendInterceptor, never()).aroundRequest(any(), any()); } }