/*
* Copyright (c) 2012 - 2016 Jadler contributors
* This program is made available under the terms of the MIT License.
*/
package net.jadler.stubbing.server.jdk;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import net.jadler.Request;
import net.jadler.RequestManager;
import net.jadler.stubbing.StubResponse;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentMatcher;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.argThat;
import static org.junit.Assert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThanOrEqualTo;
public class JdkHandlerTest {
private static final String METHOD = "GET";
private static final URI REQUEST_URI = URI.create("/abcd");
private static final byte[] REQUEST_BODY = "request body".getBytes();
private static final String REQUEST_HEADER1 = "request-header1";
private static final String REQUEST_HEADER1_VALUE1 = "request-value11";
private static final String REQUEST_HEADER1_VALUE2 = "request-value12";
private static final String REQUEST_HEADER2 = "request-header2";
private static final String REQUEST_HEADER2_VALUE1 = "request-value21";
private static final String CONTENT_TYPE_HEADER = "Content-Type";
private static final String CONTENT_TYPE_VALUE = "text/plain; charset=UTF-8";
private static final Request EXPECTED_REQUEST = Request.builder()
.body(REQUEST_BODY)
.encoding(Charset.forName("UTF-8"))
.method(METHOD)
.requestURI(REQUEST_URI)
.header(REQUEST_HEADER1, REQUEST_HEADER1_VALUE1)
.header(REQUEST_HEADER1, REQUEST_HEADER1_VALUE2)
.header(REQUEST_HEADER2, REQUEST_HEADER2_VALUE1)
.header(CONTENT_TYPE_HEADER, CONTENT_TYPE_VALUE)
.build();
private static final int RESPONSE_STATUS = 200;
private static final String RESPONSE_BODY = "response body";
private static final int RESPONSE_DELAY = 1;
private static final TimeUnit RESPONSE_DELAY_UNIT = TimeUnit.SECONDS;
private static final String RESPONSE_HEADER1 = "response-header1";
private static final String RESPONSE_HEADER1_VALUE1 = "response-value11";
private static final String RESPONSE_HEADER1_VALUE2 = "response-value12";
private static final String RESPONSE_HEADER2 = "response-header2";
private static final String RESPONSE_HEADER2_VALUE1 = "response-value21";
private HttpExchange httpExchange;
private RequestManager mockManager;
private Headers mockResponseHeaders;
private OutputStream mockResponseStream;
@Before
public void setUp() {
this.httpExchange = mock(HttpExchange.class);
when(httpExchange.getRequestMethod()).thenReturn(METHOD);
when(httpExchange.getRequestURI()).thenReturn(REQUEST_URI);
when(httpExchange.getRequestBody()).thenReturn(new ByteArrayInputStream(REQUEST_BODY));
final Headers requestHeaders = new Headers();
requestHeaders.add(REQUEST_HEADER1, REQUEST_HEADER1_VALUE1);
requestHeaders.add(REQUEST_HEADER1, REQUEST_HEADER1_VALUE2);
requestHeaders.add(REQUEST_HEADER2, REQUEST_HEADER2_VALUE1);
requestHeaders.add(CONTENT_TYPE_HEADER, CONTENT_TYPE_VALUE);
when(httpExchange.getRequestHeaders()).thenReturn(requestHeaders);
this.mockManager = mock(RequestManager.class);
this.mockResponseHeaders = mock(Headers.class);
when(httpExchange.getResponseHeaders()).thenReturn(mockResponseHeaders);
this.mockResponseStream = mock(OutputStream.class);
when(httpExchange.getResponseBody()).thenReturn(mockResponseStream);
}
@Test
public void constructor() {
new JdkHandler(mockManager);
}
@Test(expected = IllegalArgumentException.class)
public void constructor_fail() {
new JdkHandler(null);
}
@Test
public void handle_responseBody() throws IOException {
when(mockManager.provideStubResponseFor(reqEq(EXPECTED_REQUEST))).thenReturn(StubResponse.builder()
.status(RESPONSE_STATUS)
.body(RESPONSE_BODY.getBytes())
.delay(RESPONSE_DELAY, RESPONSE_DELAY_UNIT)
.header(RESPONSE_HEADER1, RESPONSE_HEADER1_VALUE1)
.header(RESPONSE_HEADER1, RESPONSE_HEADER1_VALUE2)
.header(RESPONSE_HEADER2, RESPONSE_HEADER2_VALUE1)
.build());
final long start = System.currentTimeMillis();
new JdkHandler(mockManager).handle(httpExchange);
assertThat(RESPONSE_DELAY_UNIT.toMillis(RESPONSE_DELAY),
is(lessThanOrEqualTo(System.currentTimeMillis() - start)));
verify(mockResponseHeaders).add(eq(RESPONSE_HEADER1), eq(RESPONSE_HEADER1_VALUE1));
verify(mockResponseHeaders).add(eq(RESPONSE_HEADER1), eq(RESPONSE_HEADER1_VALUE2));
verify(mockResponseHeaders).add(eq(RESPONSE_HEADER2), eq(RESPONSE_HEADER2_VALUE1));
verifyNoMoreInteractions(mockResponseHeaders);
verify(httpExchange).sendResponseHeaders(RESPONSE_STATUS, RESPONSE_BODY.length());
verify(mockResponseStream).write(RESPONSE_BODY.getBytes());
}
@Test
public void handle_noResponseBody() throws IOException {
when(mockManager.provideStubResponseFor(reqEq(EXPECTED_REQUEST))).thenReturn(StubResponse.builder()
.status(RESPONSE_STATUS)
.build());
new JdkHandler(mockManager).handle(httpExchange);
verify(httpExchange).sendResponseHeaders(RESPONSE_STATUS, -1);
verifyZeroInteractions(mockResponseStream);
}
private static Request reqEq(final Request req) {
return argThat(new RequestMatcher(req));
}
private static class RequestMatcher extends ArgumentMatcher<Request> {
private final Request expected;
private RequestMatcher(final Request expected) {
this.expected = expected;
}
@Override
public boolean matches(final Object argument) {
final Request arg = (Request) argument;
if (!this.expected.getMethod().equals(arg.getMethod())) {
return false;
}
if (!this.expected.getURI().equals(arg.getURI())) {
return false;
}
if (!Arrays.equals(this.expected.getBodyAsBytes(), arg.getBodyAsBytes())) {
return false;
}
if (!this.expected.getHeaders().equals(arg.getHeaders())) {
return false;
}
return this.expected.getParameters().equals(arg.getParameters());
}
}
}