/* * Copyright 2014, The Sporting Exchange Limited * Copyright 2015, Simon Matić Langford * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.betfair.cougar.client; import com.betfair.cougar.api.ExecutionContext; import com.betfair.cougar.api.ResponseCode; import com.betfair.cougar.client.api.ContextEmitter; import com.betfair.cougar.core.api.ev.ClientExecutionResult; import com.betfair.cougar.core.api.ev.ExecutionObserver; import com.betfair.cougar.core.api.ev.ExecutionResult; import com.betfair.cougar.core.api.ev.ExecutionVenue; import com.betfair.cougar.core.api.ev.OperationKey; import com.betfair.cougar.core.api.ev.TimeConstraints; import com.betfair.cougar.core.api.exception.CougarClientException; import com.betfair.cougar.core.api.client.ExceptionFactory; import com.betfair.cougar.core.api.exception.ServerFaultCode; import com.betfair.cougar.core.api.tracing.Tracer; import com.betfair.cougar.core.impl.DefaultTimeConstraints; import com.betfair.cougar.marshalling.api.databinding.Marshaller; import com.betfair.cougar.transport.api.protocol.http.HttpServiceBindingDescriptor; import com.betfair.cougar.util.RequestUUIDImpl; import com.betfair.cougar.util.UUIDGeneratorImpl; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; import org.apache.http.ProtocolVersion; import org.apache.http.StatusLine; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.message.BasicHttpResponse; import org.apache.http.message.BasicStatusLine; import org.apache.http.params.HttpParams; import org.junit.Test; import org.mockito.ArgumentCaptor; import javax.servlet.http.HttpServletResponse; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import static com.betfair.cougar.client.AbstractHttpExecutable.DEFAULT_REQUEST_UUID_PARENTS_HEADER; import static com.betfair.cougar.client.HttpClientExecutable.DEFAULT_REQUEST_UUID_HEADER; import static org.junit.Assert.*; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.*; /** * Unit test for @see HttpClientExecutable class */ public class HttpClientExecutableTest extends AbstractHttpExecutableTest<HttpUriRequest> { // --------------- Initialisation stuff ---------------- HttpClient mockHttpClient; CougarClientConnManager mockManager; private ContextEmitter emitter; @Override protected AbstractHttpExecutable<HttpUriRequest> makeExecutable(HttpServiceBindingDescriptor tsbd) throws Exception { mockHttpClient = mock(HttpClient.class); HttpResponse response = mock(HttpResponse.class); when(mockHttpClient.execute(any(HttpUriRequest.class))).thenReturn(response); when(response.getStatusLine()).thenReturn(new BasicStatusLine(new ProtocolVersion("HTTP",1,1), 200, "OK")); emitter = mock(ContextEmitter.class); mockManager = mock(CougarClientConnManager.class); HttpClientExecutable ret = new HttpClientExecutable(tsbd, emitter, tracer, mockManager); ret.setClient(mockHttpClient); return ret; } protected void preInit() throws Exception { // Add dependent mocks to cougar client execution venue HttpUriRequest request = mock(HttpUriRequest.class); when(mockMethodFactory.create(any(String.class), any(String.class), any(Message.class), any(Marshaller.class), any(String.class), any(ClientCallContext.class), any(TimeConstraints.class))).thenReturn(request); HttpParams mockParams = mock(HttpParams.class); mockGetMethod = mock(HttpGet.class); when(mockGetMethod.getParams()).thenReturn(mockParams); } // --------------- Base class requirements --------------- private void mockHttpResponse(final HttpUriRequest request, final String response, final int responseCode) { final HttpResponse httpResponse = mock(HttpResponse.class); final HttpEntity entity = mock(HttpEntity.class); final StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1,responseCode,""); when(httpResponse.getEntity()).thenReturn(entity); when(httpResponse.getStatusLine()).thenReturn(statusLine); final Header cougarHeader=mock(Header.class); when(cougarHeader.getValue()).thenReturn("Cougar 2"); when(httpResponse.containsHeader("Server")).thenReturn(true); when(httpResponse.getFirstHeader("Server")).thenReturn(cougarHeader); try { final byte[] responseBytes = response.getBytes("UTF-8"); when(entity.getContent()).thenReturn(new ByteArrayInputStream(responseBytes)); when(entity.getContentLength()).thenReturn((long) responseBytes.length); } catch (final IOException e) { throw new RuntimeException(e); } try { when(mockHttpClient.execute(request)).thenReturn(httpResponse); } catch (final Exception e1) { fail(); } } @Override protected void mockAndMakeCall(HttpUriRequest httpUriRequest, int httpCode, String response, int responseSize, AbstractHttpExecutable<HttpUriRequest> client, ExecutionContext ec, OperationKey key, Object[] params, ObservableObserver observer, ExecutionVenue ev, TimeConstraints timeConstraints) throws InterruptedException { // mocks before mockHttpResponse(httpUriRequest, response, httpCode); // executes second client.execute(ec, key, params, observer, ev, timeConstraints); } @Override protected int getEVPostSuccessWithMandatoryBodyAndQueryParameterPresent_ResultSize() { return 23; } // --------------- Specific tests --------------- @Test public void testEVPostSuccessWithMandatoryBodyParameterPresent() throws Exception { HttpParams mockParams = mock(HttpParams.class); mockPostMethod = mock(HttpPost.class); when(mockPostMethod.getParams()).thenReturn(mockParams); super.testEVPostSuccessWithMandatoryBodyParameterPresent(); } @Test public void testEVPostSuccessWithMandatoryBodyAndQueryParameterPresent() throws Exception { HttpParams mockParams = mock(HttpParams.class); mockPostMethod = mock(HttpPost.class); when(mockPostMethod.getParams()).thenReturn(mockParams); super.testEVPostSuccessWithMandatoryBodyAndQueryParameterPresent(); } @Test public void testFailingCall() throws IOException { generateEV(tsd, null); HttpUriRequest mockMethod = mock(HttpUriRequest.class); final BasicHttpResponse httpResponse = new BasicHttpResponse(new BasicStatusLine(HttpVersion.HTTP_1_1, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "")); when(mockHttpClient.execute(any(HttpUriRequest.class))).thenReturn(httpResponse); when(mockMethodFactory.create(anyString(), anyString(), any(Message.class), any(Marshaller.class), anyString(), any(ClientCallContext.class), any(TimeConstraints.class))).thenReturn(mockMethod); when(mockedHttpErrorTransformer.convert(any(InputStream.class), any(ExceptionFactory.class), anyInt())).thenReturn(new CougarClientException(ServerFaultCode.RemoteCougarCommunicationFailure, "bang")); HttpParams mockParams = mock(HttpParams.class); when(mockMethod.getParams()).thenReturn(mockParams); ExecutionObserver mockedObserver = mock(ExecutionObserver.class); client.execute(createEC(null, null, false), TestServiceDefinition.TEST_MIXED, new Object[] {TEST_TEXT, TEST_TEXT }, mockedObserver, ev, DefaultTimeConstraints.NO_CONSTRAINTS); ArgumentCaptor<ExecutionResult> resultCaptor = ArgumentCaptor.forClass(ExecutionResult.class); verify(mockedObserver).onResult(resultCaptor.capture()); ExecutionResult actual = resultCaptor.getValue(); assertEquals(ExecutionResult.ResultType.Fault, actual.getResultType()); assertNotNull(actual.getFault()); assertNull(actual.getResult()); assertNull(actual.getSubscription()); assertEquals(0, ((ClientExecutionResult)actual).getResultSize()); } @Test public void testNullResponseFromServer() throws IOException { generateEV(tsd, null); HttpUriRequest mockMethod = mock(HttpUriRequest.class); final HttpResponse httpResponse = mock(HttpResponse.class); when(httpResponse.getEntity()).thenReturn(null); when(mockHttpClient.execute(any(HttpUriRequest.class))).thenReturn(httpResponse); when(mockMethodFactory.create(anyString(), anyString(), any(Message.class), any(Marshaller.class), anyString(), any(ClientCallContext.class), any(TimeConstraints.class))).thenReturn(mockMethod); when(mockedHttpErrorTransformer.convert(any(InputStream.class), any(ExceptionFactory.class), anyInt())).thenReturn(new CougarClientException(ServerFaultCode.RemoteCougarCommunicationFailure, "bang")); HttpParams mockParams = mock(HttpParams.class); when(mockMethod.getParams()).thenReturn(mockParams); final StatusLine statusLine = new BasicStatusLine(HttpVersion.HTTP_1_1,HttpServletResponse.SC_OK,""); when(httpResponse.getStatusLine()).thenReturn(statusLine); ExecutionObserver mockedObserver = mock(ExecutionObserver.class); client.execute(createEC(null, null, false), TestServiceDefinition.TEST_MIXED, new Object[] {TEST_TEXT, TEST_TEXT }, mockedObserver, ev, DefaultTimeConstraints.NO_CONSTRAINTS); ArgumentCaptor<ExecutionResult> resultCaptor = ArgumentCaptor.forClass(ExecutionResult.class); verify(mockedObserver).onResult(resultCaptor.capture()); ExecutionResult actual = resultCaptor.getValue(); assertEquals(actual.getFault().getServerFaultCode(), ServerFaultCode.RemoteCougarCommunicationFailure); assertEquals(actual.getFault().getResponseCode(), ResponseCode.ServiceUnavailable); assertEquals(0, ((ClientExecutionResult)actual).getResultSize()); } @Test public void shouldReturnTransportMetrics() throws Exception { when(mockManager.getConnectionsInPool()).thenReturn(4); when(mockManager.getFreeConnections()).thenReturn(2); when(mockManager.getDefaultMaxPerRoute()).thenReturn(10); assertEquals(4, client.getTransportMetrics().getOpenConnections()); assertEquals(2, client.getTransportMetrics().getFreeConnections()); assertEquals(10, client.getTransportMetrics().getMaximumConnections()); assertEquals(20, client.getTransportMetrics().getCurrentLoad()); } }