1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.shindig.social.opensocial.service;
19
20 import org.apache.shindig.common.testing.FakeGadgetToken;
21 import org.apache.shindig.common.testing.FakeHttpServletRequest;
22 import org.apache.shindig.common.util.ImmediateFuture;
23 import org.apache.shindig.social.ResponseError;
24 import org.apache.shindig.social.SocialApiTestsGuiceModule;
25 import org.apache.shindig.social.core.util.BeanAtomConverter;
26 import org.apache.shindig.social.core.util.BeanJsonConverter;
27 import org.apache.shindig.social.core.util.BeanXStreamAtomConverter;
28 import org.apache.shindig.social.core.util.BeanXStreamConverter;
29 import org.apache.shindig.social.core.util.BeanXmlConverter;
30 import org.apache.shindig.social.core.util.xstream.GuiceBeanProvider;
31 import org.apache.shindig.social.core.util.xstream.XStream081Configuration;
32 import org.apache.shindig.social.opensocial.spi.SocialSpiException;
33
34 import com.google.common.collect.ImmutableMap;
35 import com.google.common.collect.Maps;
36 import com.google.inject.Guice;
37 import com.google.inject.Injector;
38 import com.google.inject.Provider;
39
40 import junit.framework.TestCase;
41 import org.easymock.classextension.EasyMock;
42
43 import java.io.IOException;
44 import java.io.PrintWriter;
45 import java.util.StringTokenizer;
46 import java.util.concurrent.ExecutionException;
47 import javax.servlet.ServletInputStream;
48 import javax.servlet.http.HttpServletRequest;
49 import javax.servlet.http.HttpServletResponse;
50
51 public class DataServiceServletTest extends TestCase {
52
53 private static final FakeGadgetToken FAKE_GADGET_TOKEN = new FakeGadgetToken()
54 .setOwnerId("john.doe").setViewerId("john.doe");
55
56 private HttpServletRequest req;
57 private HttpServletResponse res;
58 private DataServiceServlet servlet;
59 private PersonHandler peopleHandler;
60 private ActivityHandler activityHandler;
61 private AppDataHandler appDataHandler;
62 private BeanJsonConverter jsonConverter;
63
64 private final ServletInputStream dummyPostData = new ServletInputStream() {
65 @Override public int read() {
66 return -1;
67 }
68 };
69
70 @Override protected void setUp() throws Exception {
71 servlet = new DataServiceServlet();
72 req = EasyMock.createMock(HttpServletRequest.class);
73 res = EasyMock.createMock(HttpServletResponse.class);
74 jsonConverter = EasyMock.createMock(BeanJsonConverter.class);
75 BeanXStreamConverter xmlConverter = EasyMock.createMock(BeanXStreamConverter.class);
76 BeanXStreamAtomConverter atomConverter = EasyMock.createMock(BeanXStreamAtomConverter.class);
77 peopleHandler = EasyMock.createMock(PersonHandler.class);
78 activityHandler = EasyMock.createMock(ActivityHandler.class);
79 appDataHandler = EasyMock.createMock(AppDataHandler.class);
80
81 EasyMock.expect(jsonConverter.getContentType()).andReturn("application/json");
82 EasyMock.expect(xmlConverter.getContentType()).andReturn("application/xml");
83 EasyMock.expect(atomConverter.getContentType()).andReturn("application/atom+xml");
84
85 HandlerDispatcher dispatcher = new StandardHandlerDispatcher(constant(peopleHandler),
86 constant(activityHandler), constant(appDataHandler));
87 servlet.setHandlerDispatcher(dispatcher);
88
89 servlet.setBeanConverters(jsonConverter, xmlConverter, atomConverter);
90 }
91
92
93 private static <T> Provider<T> constant(final T value) {
94 return new Provider<T>() {
95 public T get() {
96 return value;
97 }
98 };
99 }
100
101 public void testPeopleUriRecognition() throws Exception {
102 verifyHandlerWasFoundForPathInfo('/'
103 + DataServiceServlet.PEOPLE_ROUTE + "/5/@self", peopleHandler);
104 }
105
106 public void testActivitiesUriRecognition() throws Exception {
107 verifyHandlerWasFoundForPathInfo('/'
108 + DataServiceServlet.ACTIVITY_ROUTE + "/5/@self", activityHandler);
109 }
110
111 public void testAppDataUriRecognition() throws Exception {
112 verifyHandlerWasFoundForPathInfo('/'
113 + DataServiceServlet.APPDATA_ROUTE + "/5/@self", appDataHandler);
114 }
115
116 public void testMethodOverride() throws Exception {
117 String route = '/' + DataServiceServlet.APPDATA_ROUTE;
118 verifyHandlerWasFoundForPathInfo(route, appDataHandler, "POST", "GET", "GET");
119 verifyHandlerWasFoundForPathInfo(route, appDataHandler, "POST", "", "POST");
120 verifyHandlerWasFoundForPathInfo(route, appDataHandler, "POST", null, "POST");
121 verifyHandlerWasFoundForPathInfo(route, appDataHandler, "POST", "POST", "POST");
122 verifyHandlerWasFoundForPathInfo(route, appDataHandler, "GET", null, "GET");
123 verifyHandlerWasFoundForPathInfo(route, appDataHandler, "DELETE", null, "DELETE");
124 verifyHandlerWasFoundForPathInfo(route, appDataHandler, "PUT", null, "PUT");
125 }
126
127 /***
128 * Tests a data handler that returns a failed Future
129 */
130 public void testFailedRequest() throws Exception {
131 String route = '/' + DataServiceServlet.APPDATA_ROUTE;
132 setupRequest(route, "GET", null);
133
134 EasyMock.expect(appDataHandler.handleItem(EasyMock.isA(RestfulRequestItem.class)));
135 EasyMock.expectLastCall().andReturn(
136 ImmediateFuture.errorInstance(new RuntimeException("FAILED")));
137
138 res.sendError(500, "FAILED");
139 res.setCharacterEncoding("UTF-8");
140 res.setContentType("application/json");
141
142 EasyMock.replay(req, res, appDataHandler, jsonConverter);
143 servlet.service(req, res);
144 EasyMock.verify(req, res, appDataHandler, jsonConverter);
145 EasyMock.reset(req, res, appDataHandler, jsonConverter);
146 }
147
148 private void verifyHandlerWasFoundForPathInfo(String peoplePathInfo, DataRequestHandler handler)
149 throws Exception {
150 String post = "POST";
151 verifyHandlerWasFoundForPathInfo(peoplePathInfo, handler, post, post, post);
152 }
153
154 private void verifyHandlerWasFoundForPathInfo(String pathInfo, DataRequestHandler handler,
155 String actualMethod, String overrideMethod, String expectedMethod) throws Exception {
156 setupRequest(pathInfo, actualMethod, overrideMethod);
157
158 String jsonObject = "my lovely json";
159
160 EasyMock.expect(handler.handleItem(EasyMock.isA(RequestItem.class)));
161 EasyMock.expectLastCall().andReturn(ImmediateFuture.newInstance(jsonObject));
162
163 EasyMock.expect(jsonConverter.convertToString(ImmutableMap.of("entry", jsonObject)))
164 .andReturn("{ 'entry' : " + jsonObject + " }");
165
166 PrintWriter writerMock = EasyMock.createMock(PrintWriter.class);
167 EasyMock.expect(res.getWriter()).andReturn(writerMock);
168 writerMock.write(jsonObject);
169 res.setCharacterEncoding("UTF-8");
170 res.setContentType("application/json");
171
172 EasyMock.replay(req, res, handler, jsonConverter);
173 servlet.service(req, res);
174 EasyMock.verify(req, res, handler, jsonConverter);
175 EasyMock.reset(req, res, handler, jsonConverter);
176
177 EasyMock.expect(jsonConverter.getContentType()).andReturn("application/json");
178 }
179
180 private void setupRequest(String pathInfo, String actualMethod, String overrideMethod)
181 throws IOException {
182 EasyMock.expect(req.getCharacterEncoding()).andStubReturn("UTF-8");
183 if (!("GET").equals(overrideMethod) && !("HEAD").equals(overrideMethod)) {
184 EasyMock.expect(req.getInputStream()).andStubReturn(dummyPostData);
185 }
186 EasyMock.expect(req.getPathInfo()).andStubReturn(pathInfo);
187 EasyMock.expect(req.getMethod()).andStubReturn(actualMethod);
188 EasyMock.expect(req.getParameterNames()).andStubReturn(new StringTokenizer(""));
189 EasyMock.expect(req.getParameter(RestfulRequestItem.X_HTTP_METHOD_OVERRIDE)).andReturn(
190 overrideMethod).times(2);
191 EasyMock.expect(req.getParameter(DataServiceServlet.FORMAT_PARAM)).andReturn(null);
192
193 EasyMock.expect(req.getAttribute(EasyMock.isA(String.class))).andReturn(FAKE_GADGET_TOKEN);
194 }
195
196 public void testInvalidRoute() throws Exception {
197 RestfulRequestItem requestItem = new RestfulRequestItem("/ahhh!", "GET", null,
198 FAKE_GADGET_TOKEN, jsonConverter);
199 try {
200 servlet.handleRequestItem(requestItem, new FakeHttpServletRequest()).get();
201 fail();
202 } catch (ExecutionException ee) {
203 assertTrue(ee.getCause() instanceof SocialSpiException);
204 assertEquals(ResponseError.NOT_IMPLEMENTED, ((SocialSpiException) ee.getCause()).getError());
205 }
206 }
207
208 public void testGetConverterForRequest() throws Exception {
209
210 Injector injector = Guice.createInjector(new SocialApiTestsGuiceModule());
211 BeanJsonConverter json = new BeanJsonConverter(injector);
212 BeanXStreamConverter xml = new BeanXStreamConverter(new XStream081Configuration(injector));
213 BeanXStreamAtomConverter atom = new BeanXStreamAtomConverter(new XStream081Configuration(injector));
214 servlet.setBeanConverters(json, xml, atom);
215
216 assertConverter(atom, "atom");
217 assertConverter(xml, "xml");
218 assertConverter(json, "");
219 assertConverter(json, null);
220 assertConverter(json, "ahhhh!");
221 }
222
223 public void testGetConverterForRequestContentType() throws Exception {
224 Injector injector = Guice.createInjector(new SocialApiTestsGuiceModule());
225 BeanJsonConverter json = new BeanJsonConverter(injector);
226 BeanXStreamConverter xml = new BeanXStreamConverter(new XStream081Configuration(injector));
227 BeanXStreamAtomConverter atom = new BeanXStreamAtomConverter(new XStream081Configuration(injector));
228 servlet.setBeanConverters(json, xml, atom);
229
230 assertConverterForContentType(atom, "application/atom+xml");
231 assertConverterForContentType(xml, "application/xml");
232 assertConverterForContentType(json, "");
233 assertConverterForContentType(json, null);
234 assertConverterForContentType(json, "abcd!");
235
236 }
237
238 private void assertConverter(BeanConverter converter, String format) {
239 EasyMock.expect(req.getParameter(DataServiceServlet.FORMAT_PARAM))
240 .andReturn(format);
241 EasyMock.replay(req);
242 assertEquals(converter, servlet.getConverterForRequest(req));
243 EasyMock.verify(req);
244 EasyMock.reset(req);
245 }
246
247 private void assertConverterForContentType(BeanConverter converter,
248 String contentType) {
249 EasyMock.expect(req.getHeader(DataServiceServlet.CONTENT_TYPE)).andReturn(
250 contentType);
251 EasyMock.replay(req);
252 assertEquals(converter, servlet.getConverterForRequest(req));
253 EasyMock.verify(req);
254 EasyMock.reset(req);
255 }
256 }