/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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 org.apache.shindig.social.opensocial.service; import org.apache.shindig.common.testing.FakeGadgetToken; import org.apache.shindig.common.util.ImmediateFuture; import org.apache.shindig.social.EasyMockTestCase; import org.apache.shindig.social.core.util.BeanJsonConverter; import org.apache.shindig.social.core.util.BeanXStreamAtomConverter; import org.apache.shindig.social.core.util.BeanXStreamConverter; import com.google.common.collect.ImmutableMap; import com.google.inject.Provider; import org.easymock.classextension.EasyMock; import org.json.JSONArray; import org.json.JSONObject; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.concurrent.Future; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * */ public class JsonRpcServletTest extends EasyMockTestCase { private static final FakeGadgetToken FAKE_GADGET_TOKEN = new FakeGadgetToken() .setOwnerId("john.doe").setViewerId("john.doe"); private HttpServletRequest req; private HttpServletResponse res; private JsonRpcServlet servlet; private PersonHandler peopleHandler; private ActivityHandler activityHandler; private AppDataHandler appDataHandler; private BeanJsonConverter jsonConverter; private BeanXStreamConverter xmlConverter; @Override protected void setUp() throws Exception { servlet = new JsonRpcServlet(); req = EasyMock.createMock(HttpServletRequest.class); res = EasyMock.createMock(HttpServletResponse.class); jsonConverter = EasyMock.createMock(BeanJsonConverter.class); xmlConverter = EasyMock.createMock(BeanXStreamConverter.class); BeanXStreamAtomConverter atomConverter = EasyMock.createMock(BeanXStreamAtomConverter.class); peopleHandler = EasyMock.createMock(PersonHandler.class); activityHandler = EasyMock.createMock(ActivityHandler.class); appDataHandler = EasyMock.createMock(AppDataHandler.class); HandlerDispatcher dispatcher = new StandardHandlerDispatcher(constant(peopleHandler), constant(activityHandler), constant(appDataHandler)); servlet.setHandlerDispatcher(dispatcher); servlet.setBeanConverters(jsonConverter, xmlConverter, atomConverter); } // TODO: replace with Providers.of() when Guice version is upgraded private static <T> Provider<T> constant(final T value) { return new Provider<T>() { public T get() { return value; } }; } public void testPeopleMethodRecognition() throws Exception { verifyHandlerWasFoundForMethod("{method:people.get,id:id,params:{userId:5,groupId:@self}}", peopleHandler); } public void testActivitiesMethodRecognition() throws Exception { verifyHandlerWasFoundForMethod("{method:activities.get,id:id,params:{userId:5,groupId:@self}}", activityHandler); } public void testAppDataMethodRecognition() throws Exception { verifyHandlerWasFoundForMethod("{method:appdata.get,id:id,params:{userId:5,groupId:@self}}", appDataHandler); } public void testInvalidService() throws Exception { String json = "{method:junk.get,id:id,params:{userId:5,groupId:@self}}"; setupRequest(json); JSONObject err = new JSONObject( "{id:id,error:{message:'notImplemented: The service junk is not implemented',code:501}}"); PrintWriter writerMock = EasyMock.createMock(PrintWriter.class); EasyMock.expect(res.getWriter()).andReturn(writerMock); writerMock.write(EasyMock.eq(err.toString())); EasyMock.expectLastCall(); EasyMock.replay(req, res, jsonConverter, writerMock); servlet.service(req, res); EasyMock.verify(req, res, jsonConverter, writerMock); EasyMock.reset(req, res, jsonConverter); } /** * Tests a data handler that returns a failed Future. * @throws Exception on failure */ public void testFailedRequest() throws Exception { setupRequest("{id:id,method:appdata.get}"); EasyMock.expect(appDataHandler.handleItem(EasyMock.isA(RpcRequestItem.class))); EasyMock.expectLastCall().andReturn( ImmediateFuture.errorInstance(new RuntimeException("FAILED"))); JSONObject err = new JSONObject( "{id:id,error:{message:'internalError: FAILED',code:500}}"); PrintWriter writerMock = EasyMock.createMock(PrintWriter.class); EasyMock.expect(res.getWriter()).andReturn(writerMock); writerMock.write(EasyMock.eq(err.toString())); EasyMock.expectLastCall(); EasyMock.replay(req, res, appDataHandler, jsonConverter, writerMock); servlet.service(req, res); EasyMock.verify(req, res, appDataHandler, jsonConverter, writerMock); EasyMock.reset(req, res, appDataHandler, jsonConverter); } private void verifyHandlerWasFoundForMethod(String json, DataRequestHandler handler) throws Exception { setupRequest(json); String resultObject = "my lovely json"; EasyMock.expect(handler.handleItem(EasyMock.isA(RequestItem.class))); EasyMock.expectLastCall().andReturn(ImmediateFuture.newInstance(resultObject)); EasyMock.expect(jsonConverter.convertToJson(resultObject)) .andReturn(new JSONObject(ImmutableMap.of("foo", "bar"))); JSONObject result = new JSONObject(); result.put("id", "id"); result.put("data", ImmutableMap.of("foo", "bar")); PrintWriter writerMock = EasyMock.createMock(PrintWriter.class); EasyMock.expect(res.getWriter()).andReturn(writerMock); writerMock.write(EasyMock.eq(result.toString())); EasyMock.expectLastCall(); EasyMock.replay(req, res, handler, jsonConverter, writerMock); servlet.service(req, res); EasyMock.verify(req, res, handler, jsonConverter, writerMock); EasyMock.reset(req, res, handler, jsonConverter); } public void testBasicBatch() throws Exception { String batchJson = "[{method:people.get,id:'1'},{method:activities.get,id:'2'}]"; setupRequest(batchJson); String resultObject = "my lovely json"; Future<?> responseItemFuture = ImmediateFuture.newInstance(resultObject); EasyMock.expect(peopleHandler.handleItem(EasyMock.isA(RequestItem.class))); EasyMock.expectLastCall().andReturn(responseItemFuture); EasyMock.expect(activityHandler.handleItem(EasyMock.isA(RequestItem.class))); EasyMock.expectLastCall().andReturn(responseItemFuture); EasyMock.expect(jsonConverter.convertToJson(resultObject)) .andStubReturn(new JSONObject(ImmutableMap.of("foo", "bar"))); JSONArray result = new JSONArray("[{id:'1',data:{foo:'bar'}}," + "{id:'2',data:{foo:'bar'}}]"); PrintWriter writerMock = EasyMock.createMock(PrintWriter.class); EasyMock.expect(res.getWriter()).andReturn(writerMock); writerMock.write(EasyMock.eq(result.toString())); EasyMock.expectLastCall(); EasyMock.replay(req, res, peopleHandler, activityHandler, jsonConverter, writerMock); servlet.service(req, res); EasyMock.verify(req, res, peopleHandler, activityHandler, jsonConverter, writerMock); EasyMock.reset(req, res, peopleHandler, activityHandler, jsonConverter); } public void testGetExecution() throws Exception { EasyMock.expect(req.getParameterMap()).andStubReturn( ImmutableMap.of("method", new String[]{"people.get"}, "id", new String[]{"1"})); EasyMock.expect(req.getMethod()).andStubReturn("GET"); EasyMock.expect(req.getAttribute(EasyMock.isA(String.class))).andReturn(FAKE_GADGET_TOKEN); EasyMock.expect(req.getCharacterEncoding()).andStubReturn("UTF-8"); res.setCharacterEncoding("UTF-8"); String resultObject = "my lovely json"; Future<?> responseItemFuture = ImmediateFuture.newInstance(resultObject); EasyMock.expect(peopleHandler.handleItem(EasyMock.isA(RequestItem.class))); EasyMock.expectLastCall().andReturn(responseItemFuture); EasyMock.expect(jsonConverter.convertToJson(resultObject)) .andReturn(new JSONObject(ImmutableMap.of("foo", "bar"))); JSONObject result = new JSONObject("{id:'1',data:{foo:'bar'}}"); PrintWriter writerMock = EasyMock.createMock(PrintWriter.class); EasyMock.expect(res.getWriter()).andReturn(writerMock); writerMock.write(EasyMock.eq(result.toString())); EasyMock.expectLastCall(); EasyMock.replay(req, res, peopleHandler, activityHandler, jsonConverter, writerMock); servlet.service(req, res); EasyMock.verify(req, res, peopleHandler, activityHandler, jsonConverter, writerMock); EasyMock.reset(req, res, peopleHandler, activityHandler, jsonConverter); } private void setupRequest(String json) throws IOException { final InputStream in = new ByteArrayInputStream(json.getBytes()); ServletInputStream stream = new ServletInputStream() { @Override public int read() throws IOException { return in.read(); } }; EasyMock.expect(req.getInputStream()).andStubReturn(stream); EasyMock.expect(req.getMethod()).andStubReturn("POST"); EasyMock.expect(req.getAttribute(EasyMock.isA(String.class))).andReturn(FAKE_GADGET_TOKEN); EasyMock.expect(req.getCharacterEncoding()).andStubReturn("UTF-8"); res.setCharacterEncoding("UTF-8"); res.setContentType("application/json"); } }