package com.tinkerpop.rexster; import com.tinkerpop.blueprints.Graph; import com.tinkerpop.rexster.extension.ExtensionConfiguration; import com.tinkerpop.rexster.extension.ExtensionDefinition; import com.tinkerpop.rexster.extension.ExtensionMethod; import com.tinkerpop.rexster.extension.ExtensionPoint; import com.tinkerpop.rexster.extension.ExtensionResponse; import com.tinkerpop.rexster.extension.ExtensionSegmentSet; import com.tinkerpop.rexster.extension.HttpMethod; import com.tinkerpop.rexster.extension.RexsterExtension; import com.tinkerpop.rexster.gremlin.GremlinExtension; import com.tinkerpop.rexster.server.RexsterApplication; import junit.framework.Assert; import org.codehaus.jettison.json.JSONObject; import org.jmock.Expectations; import org.jmock.Mockery; import org.jmock.integration.junit4.JUnit4Mockery; import org.junit.Before; import org.junit.Test; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.PathSegment; import javax.ws.rs.core.UriInfo; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; /** * @author Stephen Mallette (http://stephen.genoprime.com) */ public class AbstractSubResourceTest { private Mockery mockery = new JUnit4Mockery(); private MockAbstractSubResource mockResource; @Before public void init() { this.mockery = new JUnit4Mockery(); final UriInfo uriInfo = this.mockery.mock(UriInfo.class); final HttpServletRequest req = this.mockery.mock(HttpServletRequest.class); final Graph graph = this.mockery.mock(Graph.class); final RexsterApplicationGraph rag = new RexsterApplicationGraph("graph", graph); final RexsterApplication ra = this.mockery.mock(RexsterApplication.class); this.mockery.checking(new Expectations() {{ allowing(req).getParameterMap(); will(returnValue(new HashMap<String, String>())); allowing(ra).getApplicationGraph(with(any(String.class))); will(returnValue(rag)); }}); this.mockResource = new MockAbstractSubResource(uriInfo, req, ra); } @Test public void findExtensionGraphExtensionNotPresent() { this.mockery = new JUnit4Mockery(); UriInfo uri = this.mockTheUri("not", "here", ""); List<RexsterExtension> extensions = this.mockResource.findExtensionExposed(new ExtensionSegmentSet(uri, ExtensionPoint.GRAPH)); Assert.assertNull(extensions); } @Test public void findExtensionGraphExtensionFound() { this.mockery = new JUnit4Mockery(); UriInfo uri = this.mockTheUri("tp", "gremlin", ""); List<RexsterExtension> extensions = this.mockResource.findExtensionExposed(new ExtensionSegmentSet(uri, ExtensionPoint.GRAPH)); Assert.assertNotNull(extensions); Assert.assertTrue(extensions.get(0) instanceof GremlinExtension); } @Test public void findExtensionMethodNotPresent() { List<RexsterExtension> rexsterExtensions = new ArrayList<RexsterExtension>(); rexsterExtensions.add(new MockRexsterExtension()); ExtensionMethod m = this.mockResource.findExtensionMethodExposed(rexsterExtensions, ExtensionPoint.VERTEX, "action", HttpMethod.ANY); Assert.assertNull(m); } @Test public void findExtensionMethodFoundRoot() { List<RexsterExtension> rexsterExtensions = new ArrayList<RexsterExtension>(); rexsterExtensions.add(new MockRexsterExtension()); ExtensionMethod m = this.mockResource.findExtensionMethodExposed(rexsterExtensions, ExtensionPoint.GRAPH, "", HttpMethod.ANY); Assert.assertNotNull(m); Method methodFound = m.getMethod(); Assert.assertNotNull(methodFound); Assert.assertEquals("doRoot", methodFound.getName()); } @Test public void findExtensionMethodFoundSpecificAction() { List<RexsterExtension> rexsterExtensions = new ArrayList<RexsterExtension>(); rexsterExtensions.add(new MockRexsterExtension()); ExtensionMethod m = this.mockResource.findExtensionMethodExposed(rexsterExtensions, ExtensionPoint.GRAPH, "action", HttpMethod.ANY); Assert.assertNotNull(m); Method methodFound = m.getMethod(); Assert.assertNotNull(methodFound); Assert.assertEquals("doAction", methodFound.getName()); } @Test public void findExtensionMethodFoundSpecificActionMultipleExtensionClasses() { List<RexsterExtension> rexsterExtensions = new ArrayList<RexsterExtension>(); rexsterExtensions.add(new MockRexsterExtension()); rexsterExtensions.add(new MockAddOnRexsterExtension()); ExtensionMethod m = this.mockResource.findExtensionMethodExposed(rexsterExtensions, ExtensionPoint.GRAPH, "action", HttpMethod.ANY); Assert.assertNotNull(m); Method methodFound = m.getMethod(); Assert.assertNotNull(methodFound); Assert.assertEquals("doAction", methodFound.getName()); m = this.mockResource.findExtensionMethodExposed(rexsterExtensions, ExtensionPoint.GRAPH, "addon", HttpMethod.ANY); Assert.assertNotNull(m); methodFound = m.getMethod(); Assert.assertNotNull(methodFound); Assert.assertEquals("doAddOnAction", methodFound.getName()); } @Test public void findExtensionMethodFoundUseRootMethod() { List<RexsterExtension> rexsterExtensions = new ArrayList<RexsterExtension>(); rexsterExtensions.add(new MockRexsterExtension()); ExtensionMethod m = this.mockResource.findExtensionMethodExposed(rexsterExtensions, ExtensionPoint.GRAPH, "headonly", HttpMethod.POST); Assert.assertNotNull(m); Method methodFound = m.getMethod(); Assert.assertNotNull(methodFound); Assert.assertEquals("doRoot", methodFound.getName()); } @Test public void findExtensionMethodMultipleRootCheck() { List<RexsterExtension> rexsterExtensions = new ArrayList<RexsterExtension>(); rexsterExtensions.add(new MockMultiRootRexsterExtension()); ExtensionMethod m = this.mockResource.findExtensionMethodExposed(rexsterExtensions, ExtensionPoint.GRAPH, "", HttpMethod.GET); Assert.assertNotNull(m); Method methodFound = m.getMethod(); Assert.assertNotNull(methodFound); Assert.assertEquals("doRootGet", methodFound.getName()); // validates that the second method will get found m = this.mockResource.findExtensionMethodExposed(rexsterExtensions, ExtensionPoint.GRAPH, "", HttpMethod.POST); Assert.assertNotNull(m); methodFound = m.getMethod(); Assert.assertNotNull(methodFound); Assert.assertEquals("doRootPost", methodFound.getName()); } @Test public void findExtensionMethodFoundSpecificActionAndMethod() { List<RexsterExtension> rexsterExtensions = new ArrayList<RexsterExtension>(); rexsterExtensions.add(new MockRexsterExtension()); ExtensionMethod m = this.mockResource.findExtensionMethodExposed(rexsterExtensions, ExtensionPoint.GRAPH, "headonly", HttpMethod.HEAD); Assert.assertNotNull(m); Method methodFound = m.getMethod(); Assert.assertNotNull(methodFound); Assert.assertEquals("headAccessOnly", methodFound.getName()); } @Test public void tryAppendRexsterAttributesIfJsonNonJsonMediaType() { ExtensionResponse responseFromExtension = ExtensionResponse.noContent(); ExtensionResponse extResponse = this.mockResource.tryAppendRexsterAttributesIfJsonExposed( responseFromExtension, null, MediaType.APPLICATION_FORM_URLENCODED); Assert.assertNotNull(extResponse); Assert.assertEquals(responseFromExtension, extResponse); } @Test public void tryAppendRexsterAttributesIfJsonConfiguredNo() { ExtensionResponse responseFromExtension = ExtensionResponse.noContent(); final ExtensionDefinition extensionDefinition = this.mockery.mock(ExtensionDefinition.class); this.mockery.checking(new Expectations() {{ allowing(extensionDefinition).tryIncludeRexsterAttributes(); will(returnValue(false)); }}); ExtensionMethod extensionMethod = new ExtensionMethod(null, extensionDefinition, null, new MockRexsterExtension()); ExtensionResponse extResponse = this.mockResource.tryAppendRexsterAttributesIfJsonExposed( responseFromExtension, extensionMethod, MediaType.APPLICATION_JSON); Assert.assertNotNull(extResponse); Assert.assertEquals(responseFromExtension, extResponse); } @Test public void tryAppendRexsterAttributesIfJsonNotJsonInEntity() { ExtensionResponse responseFromExtension = ExtensionResponse.noContent(); final ExtensionDefinition extensionDefinition = this.mockery.mock(ExtensionDefinition.class); this.mockery.checking(new Expectations() {{ allowing(extensionDefinition).tryIncludeRexsterAttributes(); will(returnValue(true)); }}); ExtensionMethod extensionMethod = new ExtensionMethod(null, extensionDefinition, null, new MockRexsterExtension()); ExtensionResponse extResponse = this.mockResource.tryAppendRexsterAttributesIfJsonExposed( responseFromExtension, extensionMethod, MediaType.APPLICATION_JSON); Assert.assertNotNull(extResponse); Assert.assertEquals(responseFromExtension, extResponse); } @Test public void tryAppendRexsterAttributesIfJsonValid() { HashMap map = new HashMap() {{ put("me", "you"); }}; ExtensionResponse responseFromExtension = ExtensionResponse.ok(new JSONObject(map)); final ExtensionDefinition extensionDefinition = this.mockery.mock(ExtensionDefinition.class); this.mockery.checking(new Expectations() {{ allowing(extensionDefinition).tryIncludeRexsterAttributes(); will(returnValue(true)); }}); ExtensionMethod extensionMethod = new ExtensionMethod(null, extensionDefinition, null, new MockRexsterExtension()); ExtensionResponse extResponse = this.mockResource.tryAppendRexsterAttributesIfJsonExposed( responseFromExtension, extensionMethod, MediaType.APPLICATION_JSON); Assert.assertNotNull(extResponse); JSONObject jsonObjectWithAttributes = (JSONObject) extResponse.getJerseyResponse().getEntity(); Assert.assertNotNull(jsonObjectWithAttributes); Assert.assertTrue(jsonObjectWithAttributes.has("me")); Assert.assertTrue(jsonObjectWithAttributes.has(Tokens.VERSION)); Assert.assertTrue(jsonObjectWithAttributes.has(Tokens.QUERY_TIME)); } private UriInfo mockTheUri(final String namespace, final String extension, final String method) { final UriInfo uri = this.mockery.mock(UriInfo.class); final List<PathSegment> pathSegments = new ArrayList<PathSegment>(); final PathSegment graphsPathSegment = this.mockery.mock(PathSegment.class, "graphsSegment"); final PathSegment graphPathSegment = this.mockery.mock(PathSegment.class, "graphPathSegment"); final PathSegment namespacePathSegment = this.mockery.mock(PathSegment.class, "namespacePathSegment"); final PathSegment extensionPathSegment = this.mockery.mock(PathSegment.class, "extensionPathSegment"); final PathSegment methodPathSegment = this.mockery.mock(PathSegment.class, "methodPathSegment"); pathSegments.add(graphsPathSegment); pathSegments.add(graphPathSegment); pathSegments.add(namespacePathSegment); pathSegments.add(extensionPathSegment); pathSegments.add(methodPathSegment); this.mockery.checking(new Expectations() {{ allowing(namespacePathSegment).getPath(); will(returnValue(namespace)); allowing(extensionPathSegment).getPath(); will(returnValue(extension)); allowing(methodPathSegment).getPath(); will(returnValue(method)); allowing(uri).getPathSegments(); will(returnValue(pathSegments)); }}); return uri; } private class MockAbstractSubResource extends AbstractSubResource { public MockAbstractSubResource(UriInfo ui, HttpServletRequest req, RexsterApplication ra) { super(ra); this.httpServletRequest = req; this.uriInfo = ui; extensionCache.clear(); } public List<RexsterExtension> findExtensionExposed(ExtensionSegmentSet extensionSegmentSet) { return findExtensionClasses(extensionSegmentSet); } public ExtensionMethod findExtensionMethodExposed( List<RexsterExtension> rexsterExtensions, ExtensionPoint extensionPoint, String extensionAction, HttpMethod httpMethodRequested) { return findExtensionMethod(rexsterExtensions, extensionPoint, extensionAction, httpMethodRequested); } public ExtensionSegmentSet parseUriForExtensionSegmentExposed(String graphName, ExtensionPoint extensionPoint) { return parseUriForExtensionSegment(graphName, extensionPoint); } public ExtensionResponse tryAppendRexsterAttributesIfJsonExposed(ExtensionResponse extResponse, ExtensionMethod methodToCall, String mediaType) { return tryAppendRexsterAttributesIfJson(extResponse, methodToCall, mediaType); } } private class MockRexsterExtension implements RexsterExtension { @ExtensionDefinition(extensionPoint = ExtensionPoint.GRAPH) public ExtensionResponse doRoot() { return null; } @ExtensionDefinition(extensionPoint = ExtensionPoint.GRAPH, path = "action") public ExtensionResponse doAction() { return null; } @ExtensionDefinition(extensionPoint = ExtensionPoint.GRAPH, path = "headonly", method = HttpMethod.HEAD) public ExtensionResponse headAccessOnly() { return null; } public void justIgnoreMe() { // ensuring no fails when no ExtensionDefinition annotation is supplied } public boolean isConfigurationValid(ExtensionConfiguration extensionConfiguration) { return true; } } private class MockAddOnRexsterExtension implements RexsterExtension { @ExtensionDefinition(extensionPoint = ExtensionPoint.GRAPH, path = "addon") public ExtensionResponse doAddOnAction() { return null; } public boolean isConfigurationValid(ExtensionConfiguration extensionConfiguration) { return true; } } private class MockMultiRootRexsterExtension implements RexsterExtension { @ExtensionDefinition(extensionPoint = ExtensionPoint.GRAPH, method = HttpMethod.GET) public ExtensionResponse doRootGet() { return null; } @ExtensionDefinition(extensionPoint = ExtensionPoint.GRAPH, path = "action") public ExtensionResponse justSomeJunkToBeADistraction() { return null; } @ExtensionDefinition(extensionPoint = ExtensionPoint.GRAPH, method = HttpMethod.POST) public ExtensionResponse doRootPost() { return null; } public boolean isConfigurationValid(ExtensionConfiguration extensionConfiguration) { return true; } } }