/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.translator.swagger; import static org.junit.Assert.*; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URLDecoder; import java.sql.Timestamp; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TimeZone; import javax.activation.DataSource; import javax.xml.ws.Dispatch; import javax.xml.ws.Service.Mode; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.http.HTTPBinding; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.teiid.cdk.api.TranslationUtility; import org.teiid.core.util.ObjectConverterUtil; import org.teiid.language.Call; import org.teiid.language.Command; import org.teiid.language.QueryExpression; import org.teiid.metadata.MetadataFactory; import org.teiid.translator.ExecutionContext; import org.teiid.translator.ProcedureExecution; import org.teiid.translator.ResultSetExecution; import org.teiid.translator.TranslatorException; import org.teiid.translator.WSConnection; @SuppressWarnings({ "nls", "unused" }) public class TestSwaggerQueryExecution { private ProcedureExecution helpProcedureExecute(String query, final String resultJson, String expectedURL, int responseCode) throws Exception { Map<String, Object> headers = new HashMap<String, Object>(); return helpProcedureExecute(query, resultJson, expectedURL, responseCode, true, "GET", null, headers); } private ProcedureExecution helpProcedureExecute(String query, final String resultJson, String expectedURL, int responseCode, boolean decode, String expectedMethod, String expectedInput, Map<String, Object> userHeaders) throws Exception { userHeaders.put(MessageContext.HTTP_REQUEST_HEADERS, new HashMap<String, List<String>>()); userHeaders.put(WSConnection.STATUS_CODE, new Integer(responseCode)); userHeaders.put("Content-Type", Arrays.asList("application/json")); SwaggerExecutionFactory translator = new SwaggerExecutionFactory(); translator.start(); TranslationUtility utility = new TranslationUtility( TestSwaggerMetadataProcessor .getTransformationMetadata(TestSwaggerMetadataProcessor .petstoreMetadata(translator), translator)); Command cmd = utility.parseCommand(query); ExecutionContext context = Mockito.mock(ExecutionContext.class); WSConnection connection = Mockito.mock(WSConnection.class); Dispatch<DataSource> dispatch = Mockito.mock(Dispatch.class); Mockito.stub(dispatch.getRequestContext()).toReturn(userHeaders); Mockito.stub(dispatch.getResponseContext()).toReturn(userHeaders); Mockito.stub(connection.createDispatch( Mockito.eq(HTTPBinding.HTTP_BINDING), Mockito.anyString(), Mockito.eq(DataSource.class), Mockito.eq(Mode.MESSAGE))) .toReturn(dispatch); DataSource outputDS = new DataSource() { @Override public OutputStream getOutputStream() throws IOException { return new ByteArrayOutputStream(); } @Override public String getName() { return "result"; } @Override public InputStream getInputStream() throws IOException { ByteArrayInputStream in = new ByteArrayInputStream( resultJson.getBytes()); return in; } @Override public String getContentType() { return "application/json"; } }; Mockito.stub(dispatch.invoke(Mockito.any(DataSource.class))) .toReturn(outputDS); ProcedureExecution execution = translator.createProcedureExecution( (Call) cmd, context, utility.createRuntimeMetadata(), connection); execution.execute(); ArgumentCaptor<String> endpoint = ArgumentCaptor.forClass(String.class); ArgumentCaptor<String> binding = ArgumentCaptor.forClass(String.class); ArgumentCaptor<DataSource> input = ArgumentCaptor .forClass(DataSource.class); Mockito.verify(connection).createDispatch(binding.capture(), endpoint.capture(), Mockito.eq(DataSource.class), Mockito.eq(Mode.MESSAGE)); Mockito.verify(dispatch).invoke(input.capture()); assertEquals(expectedURL, decode ? URLDecoder.decode(endpoint.getValue(), "utf-8") : endpoint.getValue()); assertEquals(expectedMethod, dispatch.getRequestContext() .get(MessageContext.HTTP_REQUEST_METHOD)); if (expectedInput != null) { assertEquals(expectedInput, ObjectConverterUtil .convertToString(input.getValue().getInputStream())); } return execution; } @Test public void testSimpleInputArray() throws Exception { String query = "exec findPetsByStatus(status=>('available',));"; String expectedURL = "http://petstore.swagger.io/v2/pet/findByStatus?status=available"; String response = "[\n" + " {\n" + "\"id\": 7,\n" + " \"category\": {\n" + " \"id\": 4,\n" + " \"name\": \"Lions\"\n" + " },\n" + " \"name\": \"Lion 1\",\n" + " \"photoUrls\": [\n" + " \"url1\",\n" + " \"url2\"\n" + " ],\n" + " \"tags\": [\n" + " {\n" + " \"id\": 1,\n" + " \"name\": \"tag1\"\n" + " },\n" + " {\n" + " \"id\": 2,\n" + " \"name\": \"tag2\"\n" + " }\n" + " ],\n" + " \"status\": \"available\"\n" + " },\n" + " {\n" + " \"id\": 10008,\n" + " \"category\": {\n" + " \"id\": 0,\n" + " \"name\": \"string\"\n" + " },\n" + " \"name\": \"doggie\",\n" + " \"photoUrls\": [\n" + " \"string\"\n" + " ],\n" + " \"tags\": [\n" + " {\n" + " \"id\": 0,\n" + " \"name\": \"string\"\n" + " }\n" + " ],\n" + " \"status\": \"available\"\n" + " }]"; ProcedureExecution excution = helpProcedureExecute(query, response, expectedURL, 200); assertArrayEquals(new Object[] { 7L, 4L, "Lions", "Lion 1", new String[] { "url1", "url2" }, 1L, "tag1", "available" }, excution.next().toArray(new Object[8])); assertArrayEquals(new Object[] { 7L, 4L, "Lions", "Lion 1", new String[] { "url1", "url2" }, 2L, "tag2", "available" }, excution.next().toArray(new Object[8])); assertArrayEquals( new Object[] { 10008L, 0L, "string", "doggie", new String[] { "string" }, 0L, "string", "available" }, excution.next().toArray(new Object[8])); assertNull(excution.next()); } @Test public void testPostBasedQuery() throws Exception { String query = "exec addPet(id=>99, category_id=>0,category_name=>'canine',name=>'nikky'," + "photoUrls=>('photo1','photo2'),tags_tag_id=>0, tags_tag_name=>'doggie'," + "status=>'available');"; String expectedURL = "http://petstore.swagger.io/v2/pet"; String response = "{" + "\"id\":99," + "\"name\":\"nikky\"," + "\"photoUrls\":[\"photo1\",\"photo2\"]," + "\"status\":\"available\"," + "\"category\":{" + "\"id\":0," + "\"name\":\"canine\"" + "}," + "\"tags\":[" + "{\"id\":0," + "\"name\":\"doggie\"" + "}" + "]}"; ProcedureExecution excution = helpProcedureExecute(query, response, expectedURL, 200, true, "POST", response, getHeaders()); } @Test public void testMapReturn() throws Exception { String query = "exec getInventory();"; String expectedURL = "http://petstore.swagger.io/v2/store/inventory"; String response = "{\n" + " \"sold\": 6,\n" + " \"string\": 7,\n" + " \"pending\": 62,\n" + " \"available\": 891,\n" + " \"Live\": 7,\n" + " \"fulfilled\": 1\n" + "}"; ProcedureExecution excution = helpProcedureExecute(query, response, expectedURL, 200, true, "GET", null, getHeaders()); assertArrayEquals(new Object[] { "sold", 6 }, excution.next().toArray(new Object[2])); assertArrayEquals(new Object[] { "string", 7 }, excution.next().toArray(new Object[2])); assertArrayEquals(new Object[] { "pending", 62 }, excution.next().toArray(new Object[2])); assertArrayEquals(new Object[] { "available", 891 }, excution.next().toArray(new Object[2])); assertArrayEquals(new Object[] { "Live", 7 }, excution.next().toArray(new Object[2])); assertArrayEquals(new Object[] { "fulfilled", 1 }, excution.next().toArray(new Object[2])); assertNull(excution.next()); } @Test public void testHeadersInResponseWithReturn() throws Exception { String query = "exec loginUser(username=>'foo',password=>'bar');"; String expectedURL = "http://petstore.swagger.io/v2/user/login?username=foo&password=bar"; String response = "sucess"; TimeZone tz = TimeZone.getDefault(); try { TimeZone.setDefault(TimeZone.getTimeZone("GMT")); ProcedureExecution excution = helpProcedureExecute(query, response, expectedURL, 200, true, "GET", null, getHeaders()); assertArrayEquals(new Object[] { "sucess", 1, new Timestamp(1460110463000L) }, excution.next().toArray(new Object[3])); assertNull(excution.next()); } finally { TimeZone.setDefault(tz); } } @Test public void testParameterInPath() throws Exception { String query = "exec getPetById(petId=>687789);"; String expectedURL = "http://petstore.swagger.io/v2/pet/687789"; String response = "{\n" + " \"id\": 687789,\n" + " \"category\": {\n" + " \"id\": 0,\n" + " \"name\": \"Lions\"\n" + " },\n" + " \"name\": \"nikky\",\n" + " \"photoUrls\": [\n" + " \"url1\"\n" + " ],\n" + " \"tags\": [\n" + " {\n" + " \"id\": 1,\n" + " \"name\": \"tag1\"\n" + " }\n" + " ],\n" + " \"status\": \"sold\"\n" + "}"; ProcedureExecution excution = helpProcedureExecute(query, response, expectedURL, 200, true, "GET", null, getHeaders()); assertArrayEquals(new Object[] { 687789L, 0L, "Lions", "nikky", new String[] { "url1"}, 1L, "tag1", "sold" }, excution.next().toArray(new Object[8])); assertNull(excution.next()); } @Test(expected=TranslatorException.class) public void testErrorResponse() throws Exception { String query = "exec getPetById(petId=>687789);"; String expectedURL = "http://petstore.swagger.io/v2/pet/687789"; String response = ""; ProcedureExecution excution = helpProcedureExecute(query, response, expectedURL, 400, true, "GET", null, getHeaders()); assertNull(excution.next()); } @Test public void testDefaultResponse() throws Exception { String query = "exec logoutUser();"; String expectedURL = "http://petstore.swagger.io/v2/user/logout"; String response = ""; ProcedureExecution excution = helpProcedureExecute(query, response, expectedURL, 200, true, "GET", null, getHeaders()); assertNull(excution.next()); } @Test public void testScalarResponse() throws Exception { String query = "exec loginStatus('foo');"; String expectedURL = "http://petstore.swagger.io/v2/user/loginStatus?username=foo"; String response = "foo"; ProcedureExecution excution = helpProcedureExecute(query, response, expectedURL, 200, true, "GET", null, getHeaders()); assertEquals("foo", excution.getOutputParameterValues().get(0)); } private Map<String, Object> getHeaders() { Map<String, Object> headers = new HashMap<String, Object>(); headers.put(MessageContext.HTTP_REQUEST_HEADERS, new HashMap<String, List<String>>()); headers.put(WSConnection.STATUS_CODE, new Integer(200)); headers.put("Content-Type", "application/json"); headers.put("X-Rate-Limit", "1"); headers.put("X-Expires-After", "2016-04-08T10:14:23Z"); return headers; } @Test public void testGetSerializer(){ assertTrue(SwaggerProcedureExecution.getSerializer("application/json") instanceof JsonSerializer); assertTrue(SwaggerProcedureExecution.getSerializer("application/json;charset=utf-8") instanceof JsonSerializer); assertTrue(SwaggerProcedureExecution.getSerializer("application/xml") instanceof XMLSerializer); assertTrue(SwaggerProcedureExecution.getSerializer("application/xml;charset=utf-8") instanceof XMLSerializer); } }