/*
* 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.RequestUUID;
import com.betfair.cougar.api.geolocation.GeoLocationDetails;
import com.betfair.cougar.client.api.GeoLocationSerializer;
import com.betfair.cougar.core.api.ev.TimeConstraints;
import com.betfair.cougar.marshalling.api.databinding.Marshaller;
import com.betfair.cougar.util.RequestUUIDImpl;
import com.betfair.cougar.util.UUIDGeneratorImpl;
import org.apache.http.Header;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.ISODateTimeFormat;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.io.ByteArrayOutputStream;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import static org.apache.http.HttpHeaders.*;
import static org.junit.Assert.*;
import static org.mockito.Matchers.*;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
public class CougarRequestFactoryTest {
private static final String CONTENT_TYPE = "application/x-my-type";
@Mock
private ClientCallContext mockCallContext;
@Mock
private Message mockMessage;
@Mock
private Marshaller mockMarshaller;
@Mock
private GeoLocationDetails mockGeoLocation;
@Mock
private GeoLocationSerializer mockGeoLocationSerializer;
@Mock
private TimeConstraints mockTimeConstraints;
private Object httpRequest = new Object();
private List<Header> headers;
private String postEntity;
private String contentType;
private String httpMethod;
private String uri = "http://some.uri/";
private static final DateTimeFormatter DATE_TIME_FORMATTER = ISODateTimeFormat.dateTime();
private TestCougarRequestFactory factory = new TestCougarRequestFactory(mockGeoLocationSerializer, "X-REQUEST-UUID", "X-REQUEST-UUID-PARENTS");
@Before
public void setUp() throws Exception {
initMocks(this);
factory.setGzipCompressionEnabled(false);
RequestUUIDImpl.setGenerator(new UUIDGeneratorImpl());
}
@Test
public void shouldMakeGetRequest() {
httpMethod = "GET";
contentType = CONTENT_TYPE;
when(mockMessage.getHeaderMap()).thenReturn(Collections.<String, Object>emptyMap());
when(mockCallContext.getRequestUUID()).thenReturn(new RequestUUIDImpl());
Object result = factory.create(uri, httpMethod, mockMessage, mockMarshaller, contentType, mockCallContext, mockTimeConstraints);
assertSame(httpRequest, result);
assertEquals(5, headers.size());
assertHeadersContains(headers, ACCEPT, contentType);
assertHeadersContains(headers, USER_AGENT, CougarRequestFactory.USER_AGENT_HEADER);
assertHeadersContains(headers, "X-REQUEST-UUID");
assertHeadersContains(headers, "X-RequestTime");
assertHeadersContains(headers, "X-RequestTimeout", "0");
}
@Test
public void shouldMakeGetRequestWithAllHeaders() {
httpMethod = "GET";
contentType = CONTENT_TYPE;
String uuid = UUID.randomUUID().toString();
Date date = new Date();
when(mockMessage.getHeaderMap()).thenReturn(Collections.singletonMap("X-My-Header", (Object) "value"));
when(mockCallContext.traceLoggingEnabled()).thenReturn(true);
RequestUUID toReturn = new RequestUUIDImpl(uuid);
when(mockCallContext.getRequestUUID()).thenReturn(toReturn.getNewSubUUID());
factory.setGzipCompressionEnabled(true);
Object result = factory.create(uri, httpMethod, mockMessage, mockMarshaller, contentType, mockCallContext, mockTimeConstraints);
assertSame(httpRequest, result);
assertEquals(9, headers.size());
assertHeadersContains(headers, ACCEPT, contentType);
assertHeadersContains(headers, USER_AGENT, CougarRequestFactory.USER_AGENT_HEADER);
assertHeadersContains(headers, ACCEPT_ENCODING, "gzip");
assertHeadersContains(headers, "X-Trace-Me", "true");
String uuidHeaderParent = assertHeadersContains(headers, "X-REQUEST-UUID-PARENTS");
assertEquals(uuid+":"+uuid,uuidHeaderParent);
String uuidHeader = assertHeadersContains(headers, "X-REQUEST-UUID");
assertNotEquals(uuid, uuidHeader);
assertHeadersContains(headers, "X-RequestTime");
assertHeadersContains(headers, "X-RequestTimeout", "0");
assertHeadersContains(headers, "X-My-Header", "value");
}
@Test
public void shouldMakePostRequest() {
httpMethod = "POST";
contentType = CONTENT_TYPE;
Answer<Void> postAnswer = new Answer<Void>() {
@Override
public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
ByteArrayOutputStream os = (ByteArrayOutputStream) invocationOnMock.getArguments()[0];
os.write("some post data".getBytes());
return null;
}
};
when(mockCallContext.getRequestUUID()).thenReturn(new RequestUUIDImpl());
when(mockMessage.getHeaderMap()).thenReturn(Collections.<String, Object>emptyMap());
doAnswer(postAnswer).when(mockMarshaller).marshall(any(ByteArrayOutputStream.class), anyObject(), anyString(), eq(true));
Object result = factory.create(uri, httpMethod, mockMessage, mockMarshaller, contentType, mockCallContext, mockTimeConstraints);
assertSame(httpRequest, result);
assertEquals(5, headers.size());
assertHeadersContains(headers, ACCEPT, contentType);
assertHeadersContains(headers, USER_AGENT, CougarRequestFactory.USER_AGENT_HEADER);
assertHeadersContains(headers, "X-REQUEST-UUID");
assertHeadersContains(headers, "X-RequestTime");
assertHeadersContains(headers, "X-RequestTimeout", "0");
assertEquals("some post data", postEntity);
}
private void assertHeadersContains(List<Header> headers, String name, String value) {
for (Header h : headers) {
if (h.getName().equals(name) && (h.getValue() == null || h.getValue().equals(value))) {
return;
}
}
fail("Did not find header '" + name + "' with value '" + value + "'");
}
private String assertHeadersContains(List<Header> headers, String name) {
for (Header h : headers) {
if (h.getName().equals(name) && (h.getValue() != null)) {
return h.getValue();
}
}
fail("Did not find header '" + name + "'");
return null; // won't happen
}
private class TestCougarRequestFactory extends CougarRequestFactory<Object> {
public TestCougarRequestFactory(GeoLocationSerializer geoLocation, String uuidHeader, String uuidParentsHeader) {
super(new HttpContextEmitter<Object>(geoLocation,uuidHeader,uuidParentsHeader));
}
@Override
protected void addHeaders(Object o, List<Header> headers) {
assertSame(httpRequest, o);
CougarRequestFactoryTest.this.headers = headers;
}
@Override
protected void addPostEntity(Object o, String postEntity, String contentType) {
assertSame(httpRequest, o);
assertSame(CougarRequestFactoryTest.this.contentType, contentType);
CougarRequestFactoryTest.this.postEntity = postEntity;
}
@Override
protected Object createRequest(String httpMethod, String uri) {
assertSame(CougarRequestFactoryTest.this.httpMethod, httpMethod);
assertSame(CougarRequestFactoryTest.this.uri, uri);
return httpRequest;
}
}
}