View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations under the License.
17   */
18  package org.apache.shindig.social.opensocial.service;
19  
20  import org.apache.shindig.common.testing.FakeGadgetToken;
21  import org.apache.shindig.common.util.ImmediateFuture;
22  import org.apache.shindig.social.core.util.BeanAtomConverter;
23  import org.apache.shindig.social.core.util.BeanJsonConverter;
24  import org.apache.shindig.social.core.util.BeanXStreamAtomConverter;
25  import org.apache.shindig.social.core.util.BeanXStreamConverter;
26  import org.apache.shindig.social.core.util.BeanXmlConverter;
27  
28  import com.google.common.collect.ImmutableMap;
29  import com.google.common.collect.Maps;
30  
31  import com.google.inject.Provider;
32  
33  import junit.framework.TestCase;
34  import org.easymock.classextension.EasyMock;
35  import org.json.JSONArray;
36  import org.json.JSONObject;
37  
38  import java.io.ByteArrayInputStream;
39  import java.io.IOException;
40  import java.io.InputStream;
41  import java.io.PrintWriter;
42  import java.util.concurrent.Future;
43  import javax.servlet.ServletInputStream;
44  import javax.servlet.http.HttpServletRequest;
45  import javax.servlet.http.HttpServletResponse;
46  
47  /***
48   *
49   */
50  public class JsonRpcServletTest extends TestCase {
51  
52    private static final FakeGadgetToken FAKE_GADGET_TOKEN = new FakeGadgetToken()
53        .setOwnerId("john.doe").setViewerId("john.doe");
54  
55    private HttpServletRequest req;
56    private HttpServletResponse res;
57    private JsonRpcServlet servlet;
58  
59    private PersonHandler peopleHandler;
60    private ActivityHandler activityHandler;
61    private AppDataHandler appDataHandler;
62  
63    private BeanJsonConverter jsonConverter;
64    private BeanXStreamConverter xmlConverter;
65  
66    @Override protected void setUp() throws Exception {
67      servlet = new JsonRpcServlet();
68      req = EasyMock.createMock(HttpServletRequest.class);
69      res = EasyMock.createMock(HttpServletResponse.class);
70      jsonConverter = EasyMock.createMock(BeanJsonConverter.class);
71      xmlConverter = EasyMock.createMock(BeanXStreamConverter.class);
72      BeanXStreamAtomConverter atomConverter = EasyMock.createMock(BeanXStreamAtomConverter.class);
73  
74      peopleHandler = EasyMock.createMock(PersonHandler.class);
75      activityHandler = EasyMock.createMock(ActivityHandler.class);
76      appDataHandler = EasyMock.createMock(AppDataHandler.class);
77  
78      HandlerDispatcher dispatcher = new StandardHandlerDispatcher(constant(peopleHandler),
79          constant(activityHandler), constant(appDataHandler));
80      servlet.setHandlerDispatcher(dispatcher);
81  
82      servlet.setBeanConverters(jsonConverter, xmlConverter, atomConverter);
83    }
84  
85    // TODO: replace with Providers.of() when Guice version is upgraded
86    private static <T> Provider<T> constant(final T value) {
87      return new Provider<T>() {
88        public T get() {
89          return value;
90        }
91      };
92    }
93  
94    public void testPeopleMethodRecognition() throws Exception {
95      verifyHandlerWasFoundForMethod("{method:people.get,id:id,params:{userId:5,groupId:@self}}",
96          peopleHandler);
97    }
98  
99    public void testActivitiesMethodRecognition() throws Exception {
100     verifyHandlerWasFoundForMethod("{method:activities.get,id:id,params:{userId:5,groupId:@self}}",
101         activityHandler);
102   }
103 
104   public void testAppDataMethodRecognition() throws Exception {
105     verifyHandlerWasFoundForMethod("{method:appdata.get,id:id,params:{userId:5,groupId:@self}}",
106         appDataHandler);
107   }
108 
109   public void testInvalidService() throws Exception {
110     String json = "{method:junk.get,id:id,params:{userId:5,groupId:@self}}";
111     setupRequest(json);
112 
113     JSONObject err = new JSONObject(
114         "{id:id,error:{message:'notImplemented: The service junk is not implemented',code:501}}");
115 
116     PrintWriter writerMock = EasyMock.createMock(PrintWriter.class);
117     EasyMock.expect(res.getWriter()).andReturn(writerMock);
118     writerMock.write(EasyMock.eq(err.toString()));
119     EasyMock.expectLastCall();
120 
121     EasyMock.replay(req, res, jsonConverter, writerMock);
122     servlet.service(req, res);
123     EasyMock.verify(req, res, jsonConverter, writerMock);
124     EasyMock.reset(req, res, jsonConverter);
125   }
126 
127 
128   /***
129    * Tests a data handler that returns a failed Future.
130    * @throws Exception on failure
131    */
132   public void testFailedRequest() throws Exception {
133     setupRequest("{id:id,method:appdata.get}");
134     EasyMock.expect(appDataHandler.handleItem(EasyMock.isA(RpcRequestItem.class)));
135     EasyMock.expectLastCall().andReturn(
136         ImmediateFuture.errorInstance(new RuntimeException("FAILED")));
137 
138     JSONObject err = new JSONObject(
139         "{id:id,error:{message:'internalError: FAILED',code:500}}");
140 
141     PrintWriter writerMock = EasyMock.createMock(PrintWriter.class);
142     EasyMock.expect(res.getWriter()).andReturn(writerMock);
143     writerMock.write(EasyMock.eq(err.toString()));
144     EasyMock.expectLastCall();
145 
146     EasyMock.replay(req, res, appDataHandler, jsonConverter, writerMock);
147     servlet.service(req, res);
148     EasyMock.verify(req, res, appDataHandler, jsonConverter, writerMock);
149     EasyMock.reset(req, res, appDataHandler, jsonConverter);
150   }
151 
152   private void verifyHandlerWasFoundForMethod(String json, DataRequestHandler handler)
153       throws Exception {
154     setupRequest(json);
155 
156     String resultObject = "my lovely json";
157 
158     EasyMock.expect(handler.handleItem(EasyMock.isA(RequestItem.class)));
159     EasyMock.expectLastCall().andReturn(ImmediateFuture.newInstance(resultObject));
160 
161     EasyMock.expect(jsonConverter.convertToJson(resultObject))
162         .andReturn(new JSONObject(ImmutableMap.of("foo", "bar")));
163 
164     JSONObject result = new JSONObject();
165     result.put("id", "id");
166     result.put("data", ImmutableMap.of("foo", "bar"));
167     PrintWriter writerMock = EasyMock.createMock(PrintWriter.class);
168     EasyMock.expect(res.getWriter()).andReturn(writerMock);
169     writerMock.write(EasyMock.eq(result.toString()));
170     EasyMock.expectLastCall();
171 
172     EasyMock.replay(req, res, handler, jsonConverter, writerMock);
173     servlet.service(req, res);
174     EasyMock.verify(req, res, handler, jsonConverter, writerMock);
175     EasyMock.reset(req, res, handler, jsonConverter);
176   }
177 
178   public void testBasicBatch() throws Exception {
179     String batchJson =
180         "[{method:people.get,id:'1'},{method:activities.get,id:'2'}]";
181     setupRequest(batchJson);
182 
183     String resultObject = "my lovely json";
184     Future<?> responseItemFuture = ImmediateFuture.newInstance(resultObject);
185     EasyMock.expect(peopleHandler.handleItem(EasyMock.isA(RequestItem.class)));
186     EasyMock.expectLastCall().andReturn(responseItemFuture);
187     EasyMock.expect(activityHandler.handleItem(EasyMock.isA(RequestItem.class)));
188     EasyMock.expectLastCall().andReturn(responseItemFuture);
189 
190     EasyMock.expect(jsonConverter.convertToJson(resultObject))
191         .andStubReturn(new JSONObject(ImmutableMap.of("foo", "bar")));
192 
193     JSONArray result = new JSONArray("[{id:'1',data:{foo:'bar'}}," + "{id:'2',data:{foo:'bar'}}]");
194     PrintWriter writerMock = EasyMock.createMock(PrintWriter.class);
195     EasyMock.expect(res.getWriter()).andReturn(writerMock);
196     writerMock.write(EasyMock.eq(result.toString()));
197     EasyMock.expectLastCall();
198 
199     EasyMock.replay(req, res, peopleHandler, activityHandler, jsonConverter, writerMock);
200     servlet.service(req, res);
201     EasyMock.verify(req, res, peopleHandler, activityHandler, jsonConverter, writerMock);
202     EasyMock.reset(req, res, peopleHandler, activityHandler, jsonConverter);
203   }
204 
205   public void testGetExecution() throws Exception {
206     EasyMock.expect(req.getParameterMap()).andStubReturn(
207         ImmutableMap.of("method", new String[]{"people.get"}, "id", new String[]{"1"}));
208     EasyMock.expect(req.getMethod()).andStubReturn("GET");
209     EasyMock.expect(req.getAttribute(EasyMock.isA(String.class))).andReturn(FAKE_GADGET_TOKEN);
210     EasyMock.expect(req.getCharacterEncoding()).andStubReturn("UTF-8");
211     res.setCharacterEncoding("UTF-8");
212 
213     String resultObject = "my lovely json";
214 
215     Future<?> responseItemFuture = ImmediateFuture.newInstance(resultObject);
216     EasyMock.expect(peopleHandler.handleItem(EasyMock.isA(RequestItem.class)));
217     EasyMock.expectLastCall().andReturn(responseItemFuture);
218 
219     EasyMock.expect(jsonConverter.convertToJson(resultObject))
220         .andReturn(new JSONObject(ImmutableMap.of("foo", "bar")));
221 
222     JSONObject result = new JSONObject("{id:'1',data:{foo:'bar'}}");
223     PrintWriter writerMock = EasyMock.createMock(PrintWriter.class);
224     EasyMock.expect(res.getWriter()).andReturn(writerMock);
225     writerMock.write(EasyMock.eq(result.toString()));
226     EasyMock.expectLastCall();
227 
228     EasyMock.replay(req, res, peopleHandler, activityHandler, jsonConverter, writerMock);
229     servlet.service(req, res);
230     EasyMock.verify(req, res, peopleHandler, activityHandler, jsonConverter, writerMock);
231     EasyMock.reset(req, res, peopleHandler, activityHandler, jsonConverter);
232   }
233 
234   private void setupRequest(String json) throws IOException {
235     final InputStream in = new ByteArrayInputStream(json.getBytes());
236     ServletInputStream stream = new ServletInputStream() {
237       @Override
238       public int read() throws IOException {
239         return in.read();
240       }
241     };
242 
243     EasyMock.expect(req.getInputStream()).andStubReturn(stream);
244     EasyMock.expect(req.getMethod()).andStubReturn("POST");
245     EasyMock.expect(req.getAttribute(EasyMock.isA(String.class))).andReturn(FAKE_GADGET_TOKEN);
246     EasyMock.expect(req.getCharacterEncoding()).andStubReturn("UTF-8");
247     res.setCharacterEncoding("UTF-8");
248     res.setContentType("application/json");
249   }
250 
251 }