/** * Copyright (C) 2014 Stratio (http://stratio.com) * * 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.stratio.ingestion.source.rest; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.MapAssert.entry; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.LinkedBlockingQueue; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MultivaluedMap; import org.apache.flume.Context; import org.apache.flume.Event; import org.apache.flume.event.EventBuilder; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.quartz.Scheduler; import org.quartz.SchedulerContext; import org.quartz.SchedulerException; import com.google.common.base.Charsets; import com.stratio.ingestion.source.rest.handler.DefaultRestSourceHandler; import com.stratio.ingestion.source.rest.handler.JsonRestSourceHandler; import com.stratio.ingestion.source.rest.handler.RestSourceHandler; import com.stratio.ingestion.source.rest.url.DefaultUrlHandler; import com.stratio.ingestion.source.rest.url.UrlHandler; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; import com.sun.jersey.api.client.WebResource; import com.sun.jersey.core.util.MultivaluedMapImpl; @RunWith(JUnit4.class) public class RestJobTest { RequestJob job = spy(new RequestJob()); Client client = mock(Client.class); WebResource webResource = mock(WebResource.class); ClientResponse response = mock(ClientResponse.class); JobExecutionContext context = mock(JobExecutionContext.class); Scheduler scheduler = mock(Scheduler.class); SchedulerContext schedulerContext = mock(SchedulerContext.class); LinkedBlockingQueue<Event> queue; WebResource.Builder builder = mock(WebResource.Builder.class); RestSourceHandler restSourceHandler; UrlHandler urlHandler; @Before public void setUp() throws SchedulerException { when(builder.header(anyString(), anyObject())).thenReturn(builder); when(builder.header(anyString(), anyObject())).thenReturn(builder); when(builder.get(ClientResponse.class)).thenReturn(response); when(webResource.accept(any(MediaType.class))).thenReturn(builder); when(context.getScheduler()).thenReturn(scheduler); when(scheduler.getContext()).thenReturn(schedulerContext); queue = new LinkedBlockingQueue<Event>(10); when(schedulerContext.get("queue")).thenReturn(queue); when(schedulerContext.get("client")).thenReturn(client); } @Test public void simpleGetUsingDefaultHandler() throws JobExecutionException { String goodUrl = "GOOD URL"; MultivaluedMap<String, String> responseHeaders = new MultivaluedMapImpl(); Map<String, Object> properties = new HashMap<String, Object>(); properties.put(RestSource.CONF_URL, goodUrl); properties.put(RestSource.CONF_HEADERS, "{}"); properties.put(RestSource.CONF_METHOD, "GET"); when(client.resource(goodUrl)).thenReturn(webResource); when(response.getEntity(String.class)).thenReturn("XXXXX"); when(response.getHeaders()).thenReturn(responseHeaders); when(schedulerContext.get("properties")).thenReturn(properties); restSourceHandler = initDefaultHandler(); urlHandler = new DefaultUrlHandler(); when(schedulerContext.get("restSourceHandler")).thenReturn(restSourceHandler); when(schedulerContext.get("urlHandler")).thenReturn(urlHandler); RequestJob job = new RequestJob(); job.execute(context); assertThat(queue.size()).isEqualTo(1); assertThat(new String(queue.poll().getBody()).equals("XXXXX")); } private RestSourceHandler initDefaultHandler() { return new DefaultRestSourceHandler(); } @Test public void simpleGetWithJustOneEventUsingJsonHandler() throws JobExecutionException { String goodUrl = "GOOD URL"; Map<String, Object> properties = new HashMap<String, Object>(); MultivaluedMap<String, String> responseHeaders = new MultivaluedMapImpl(); properties.put(RestSource.CONF_URL, goodUrl); properties.put(RestSource.CONF_HEADERS, "{}"); properties.put(RestSource.CONF_METHOD, "GET"); String jsonResponse = "{\"field1\": \"value1\"}"; restSourceHandler = initJsonHandler(""); urlHandler = new DefaultUrlHandler(); when(client.resource(goodUrl)).thenReturn(webResource); when(response.getEntity(String.class)).thenReturn(jsonResponse); when(response.getHeaders()).thenReturn(responseHeaders); when(schedulerContext.get("properties")).thenReturn(properties); when(schedulerContext.get("restSourceHandler")).thenReturn(restSourceHandler); when(schedulerContext.get("urlHandler")).thenReturn(urlHandler); job.execute(context); assertThat(queue.size()).isEqualTo(1); assertThat(new String(queue.poll().getBody())).isEqualTo("{\"field1\":\"value1\"}"); } private RestSourceHandler initJsonHandler(String pathValue) { RestSourceHandler jsonHandler = new JsonRestSourceHandler(); Context flumeContext = new Context(); flumeContext.put("jsonPath", pathValue); jsonHandler.configure(flumeContext); return jsonHandler; } @Test public void simpleGetWithMultipleEventsUsingJsonHandler() throws JobExecutionException { String goodUrl = "GOOD URL"; Map<String, Object> properties = new HashMap<String, Object>(); MultivaluedMap<String, String> responseHeaders = new MultivaluedMapImpl(); properties.put(RestSource.CONF_URL, goodUrl); properties.put(RestSource.CONF_HEADERS, "{}"); properties.put(RestSource.CONF_METHOD, "GET"); String jsonResponse = "[{\"field1\":\"value1\"},{\"field2\":\"value2\"}]"; restSourceHandler = initJsonHandler(""); urlHandler = new DefaultUrlHandler(); when(schedulerContext.get("urlHandler")).thenReturn(urlHandler); when(client.resource(goodUrl)).thenReturn(webResource); when(response.getEntity(String.class)).thenReturn(jsonResponse); when(response.getHeaders()).thenReturn(responseHeaders); when(schedulerContext.get("properties")).thenReturn(properties); when(schedulerContext.get("restSourceHandler")).thenReturn(restSourceHandler); job.execute(context); assertThat(queue.size()).isEqualTo(2); assertThat(new String(queue.poll().getBody())).isEqualTo("{\"field1\":\"value1\"}"); assertThat(new String(queue.poll().getBody())).isEqualTo("{\"field2\":\"value2\"}"); } @Test public void simpleGetWithMultipleEventsAndHeadersUsingJsonHandler() throws JobExecutionException { String goodUrl = "GOOD URL"; Map<String, Object> properties = new HashMap<String, Object>(); MultivaluedMap<String, String> responseHeaders = new MultivaluedMapImpl(); responseHeaders.put("header1", Arrays.asList("value1", "value2")); properties.put(RestSource.CONF_URL, goodUrl); properties.put(RestSource.CONF_HEADERS, "{}"); properties.put(RestSource.CONF_METHOD, "GET"); String jsonResponse = "[{\"field1\":\"value1\"},{\"field2\":\"value2\"}]"; restSourceHandler = initJsonHandler(""); urlHandler = new DefaultUrlHandler(); when(schedulerContext.get("urlHandler")).thenReturn(urlHandler); when(client.resource(goodUrl)).thenReturn(webResource); when(response.getEntity(String.class)).thenReturn(jsonResponse); when(response.getHeaders()).thenReturn(responseHeaders); when(schedulerContext.get("properties")).thenReturn(properties); when(schedulerContext.get("restSourceHandler")).thenReturn(restSourceHandler); job.execute(context); assertThat(queue.size()).isEqualTo(2); Event poll = queue.poll(); assertThat(new String(poll.getBody())).isEqualTo("{\"field1\":\"value1\"}"); assertThat(poll.getHeaders()).includes(entry("header1", "value1, value2")); poll = queue.poll(); assertThat(new String(poll.getBody())).isEqualTo("{\"field2\":\"value2\"}"); assertThat(poll.getHeaders()).includes(entry("header1", "value1, value2")); } @Test public void simpleGetWithMultipleEventsAndHeadersUsingJsonHandlerAndPath() throws JobExecutionException { String goodUrl = "GOOD URL"; Map<String, Object> properties = new HashMap<String, Object>(); MultivaluedMap<String, String> responseHeaders = new MultivaluedMapImpl(); responseHeaders.put("header1", Arrays.asList("value1", "value2")); properties.put(RestSource.CONF_URL, goodUrl); properties.put(RestSource.CONF_HEADERS, "{}"); properties.put(RestSource.CONF_METHOD, "GET"); String jsonResponse = "[{\"field1\":\"value1\",\"field2\":\"value2\",\"data\":{\"dataField1\":1," + "\"dataField2\":\"value1\"}},{\"field1\":\"value1\",\"field2\":\"value2\",\"data\":{\"dataField1\":1,\"dataField2\":\"value2\"}}]"; urlHandler = new DefaultUrlHandler(); restSourceHandler = initJsonHandler("data"); when(schedulerContext.get("urlHandler")).thenReturn(urlHandler); when(client.resource(goodUrl)).thenReturn(webResource); when(response.getEntity(String.class)).thenReturn(jsonResponse); when(response.getHeaders()).thenReturn(responseHeaders); when(schedulerContext.get("properties")).thenReturn(properties); when(schedulerContext.get("restSourceHandler")).thenReturn(restSourceHandler); job.execute(context); assertThat(queue.size()).isEqualTo(2); Event poll = queue.poll(); assertThat(new String(poll.getBody())).isEqualTo("{\"dataField1\":1,\"dataField2\":\"value1\"}"); assertThat(poll.getHeaders()).includes(entry("header1", "value1, value2")); poll = queue.poll(); assertThat(new String(poll.getBody())).isEqualTo("{\"dataField1\":1,\"dataField2\":\"value2\"}"); assertThat(poll.getHeaders()).includes(entry("header1", "value1, value2")); } @Test public void testMultivaluedHeader() throws JobExecutionException { String goodUrl = "GOOD URL"; when(client.resource(goodUrl)).thenReturn(webResource); //Create Properties Map<String, Object> properties = new HashMap<String, Object>(); properties.put(RestSource.CONF_URL, goodUrl); properties.put(RestSource.CONF_HEADERS, "{}"); properties.put(RestSource.CONF_METHOD, "GET"); when(response.getEntity(String.class)).thenReturn("XXXXX"); //Return headers MultivaluedMap<String, String> responseHeaders = new MultivaluedMapImpl(); responseHeaders.put("GOODHEADER", Arrays.asList("aa", "bb")); restSourceHandler = initDefaultHandler(); urlHandler = new DefaultUrlHandler(); when(schedulerContext.get("urlHandler")).thenReturn(urlHandler); when(response.getHeaders()).thenReturn(responseHeaders); when(schedulerContext.get("properties")).thenReturn(properties); when(schedulerContext.get("restSourceHandler")).thenReturn(restSourceHandler); job.execute(context); assertEquals(queue.size(), 1); assertEquals(queue.poll().getHeaders().get("GOODHEADER"), "aa, bb"); } @Test public void getLastEvent() throws Exception { List<Event> events = new ArrayList<Event>(); events.add(buildEvent("{\"dataField1\":1,\"dataField1\":\"value1\"}")); events.add(buildEvent("{\"dataField2\":2,\"dataField2\":\"value2\"}")); events.add(buildEvent("{\"dataField3\":3,\"dataField3\":\"value3\"}")); final String lastEvent = job.getLastEvent(events); assertThat(lastEvent).isNotEmpty().isEqualToIgnoringCase("{\"dataField3\":3,\"dataField3\":\"value3\"}"); } private Event buildEvent(String json) { Event event = EventBuilder.withBody(json, Charsets.UTF_8, new HashMap<String, String>()); return event; } }