View Javadoc

1   /*
2    * $Id: JSONInterceptorTest.java 799110 2009-07-29 22:44:26Z musachy $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  package org.apache.struts2.json;
22  
23  import java.util.Calendar;
24  import java.util.List;
25  import java.util.Map;
26  
27  import org.apache.struts2.StrutsStatics;
28  import org.apache.struts2.StrutsTestCase;
29  import org.springframework.mock.web.MockHttpServletRequest;
30  import org.springframework.mock.web.MockHttpServletResponse;
31  import org.springframework.mock.web.MockServletContext;
32  
33  import com.opensymphony.xwork2.ActionContext;
34  import com.opensymphony.xwork2.mock.MockActionInvocation;
35  import com.opensymphony.xwork2.util.ValueStack;
36  
37  public class JSONInterceptorTest extends StrutsTestCase {
38      private MockActionInvocationEx invocation;
39      private MockHttpServletRequest request;
40      private MockHttpServletResponse response;
41  
42      private void setRequestContent(String fileName) throws Exception {
43          String content = TestUtils.readContent(JSONInterceptorTest.class.getResource(fileName));
44          this.request.setContent(content.getBytes());
45      }
46  
47      public void testBadJSON1() throws Exception {
48          tryBadJSON("bad-1.txt");
49      }
50  
51      public void testBadJSON2() throws Exception {
52          tryBadJSON("bad-2.txt");
53      }
54  
55      public void testBadJSON3() throws Exception {
56          tryBadJSON("bad-3.txt");
57      }
58  
59      public void testBadJSON4() throws Exception {
60          tryBadJSON("bad-4.txt");
61      }
62  
63      public void testBadJSON5() throws Exception {
64          tryBadJSON("bad-5.txt");
65      }
66  
67      public void testBadToTheBoneJSON4() throws Exception {
68          tryBadJSON("bad-to-the-bone.txt");
69      }
70  
71      private void tryBadJSON(String fileName) throws Exception {
72          // request
73          setRequestContent(fileName);
74          this.request.addHeader("content-type", "application/json-rpc");
75  
76          JSONInterceptor interceptor = new JSONInterceptor();
77          interceptor.setEnableSMD(true);
78          SMDActionTest1 action = new SMDActionTest1();
79  
80          this.invocation.setAction(action);
81  
82          // JSON is not well formed, throw exception
83          try {
84              interceptor.intercept(this.invocation);
85              fail("Should have thrown an exception");
86          } catch (JSONException e) {
87              // I can't get JUnit to ignore the exception
88              // @Test(expected = JSONException.class)
89          }
90      }
91  
92      public void testSMDDisabledSMD() throws Exception {
93          // request
94          setRequestContent("smd-3.txt");
95          this.request.addHeader("content-type", "application/json-rpc");
96  
97          JSONInterceptor interceptor = new JSONInterceptor();
98          SMDActionTest1 action = new SMDActionTest1();
99  
100         this.invocation.setAction(action);
101 
102         // SMD was not enabled so invocation must happen
103         try {
104             interceptor.intercept(this.invocation);
105         } catch (JSONException e) {
106             fail("Should have not thrown an exception");
107         }
108 
109     }
110 
111     public void testSMDAliasedMethodCall1() throws Exception {
112         // request
113         setRequestContent("smd-14.txt");
114         this.request.addHeader("content-type", "application/json-rpc");
115 
116         JSONInterceptor interceptor = new JSONInterceptor();
117         interceptor.setEnableSMD(true);
118         SMDActionTest2 action = new SMDActionTest2();
119 
120         this.invocation.setAction(action);
121 
122         interceptor.intercept(this.invocation);
123         // method was aliased, but was invoked with the regular name
124         // so method must not be invoked
125         assertFalse(this.invocation.isInvoked());
126         assertFalse(action.isDoSomethingInvoked());
127     }
128 
129     public void testSMDAliasedMethodCall2() throws Exception {
130         // request
131         setRequestContent("smd-15.txt");
132         this.request.addHeader("content-type", "application/json-rpc");
133 
134         JSONInterceptor interceptor = new JSONInterceptor();
135         interceptor.setEnableSMD(true);
136         SMDActionTest2 action = new SMDActionTest2();
137 
138         this.invocation.setAction(action);
139 
140         interceptor.intercept(this.invocation);
141         // method was aliased, but was invoked with the aliased name
142         // so method must be invoked
143         assertFalse(this.invocation.isInvoked());
144         assertTrue(action.isDoSomethingInvoked());
145     }
146 
147     public void testSMDNoMethod() throws Exception {
148         // request
149         setRequestContent("smd-4.txt");
150         this.request.addHeader("content-type", "application/json-rpc");
151 
152         JSONInterceptor interceptor = new JSONInterceptor();
153         interceptor.setEnableSMD(true);
154         SMDActionTest1 action = new SMDActionTest1();
155 
156         this.invocation.setAction(action);
157 
158         // SMD was enabled so invocation must happen
159 
160         interceptor.intercept(this.invocation);
161 
162         String json = response.getContentAsString();
163 
164         String normalizedActual = TestUtils.normalize(json, true);
165         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("smd-13.txt"));
166         assertEquals(normalizedExpected, normalizedActual);
167 
168         assertFalse(this.invocation.isInvoked());
169     }
170 
171     public void testSMDMethodWithoutAnnotations() throws Exception {
172         // request
173         setRequestContent("smd-9.txt");
174         this.request.addHeader("content-type", "application/json-rpc");
175 
176         JSONInterceptor interceptor = new JSONInterceptor();
177         interceptor.setEnableSMD(true);
178         SMDActionTest1 action = new SMDActionTest1();
179 
180         this.invocation.setAction(action);
181 
182         // SMD was enabled so invocation must happen
183         try {
184             interceptor.intercept(this.invocation);
185             assertTrue("Exception was expected here!", true);
186         } catch (Exception e) {
187             // ok
188         }
189         assertFalse(this.invocation.isInvoked());
190     }
191 
192     public void testSMDPrimitivesNoResult() throws Exception {
193         // request
194         setRequestContent("smd-6.txt");
195         this.request.addHeader("content-type", "application/json-rpc");
196 
197         JSONInterceptor interceptor = new JSONInterceptor();
198         interceptor.setEnableSMD(true);
199         SMDActionTest1 action = new SMDActionTest1();
200 
201         this.invocation.setAction(action);
202 
203         // can't be invoked
204         interceptor.intercept(this.invocation);
205         assertFalse(this.invocation.isInvoked());
206 
207         // asert values were passed properly
208         assertEquals("string", action.getStringParam());
209         assertEquals(1, action.getIntParam());
210         assertEquals(true, action.isBooleanParam());
211         assertEquals('c', action.getCharParam());
212         assertEquals(2, action.getLongParam());
213         assertEquals(new Float(3.3), action.getFloatParam());
214         assertEquals(4.4, action.getDoubleParam());
215         assertEquals(5, action.getShortParam());
216         assertEquals(6, action.getByteParam());
217 
218         String json = response.getContentAsString();
219 
220         String normalizedActual = TestUtils.normalize(json, true);
221         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("smd-11.txt"));
222         assertEquals(normalizedExpected, normalizedActual);
223 
224         assertEquals("application/json-rpc;charset=ISO-8859-1", response.getContentType());
225     }
226 
227     public void testSMDReturnObject() throws Exception {
228         // request
229         setRequestContent("smd-10.txt");
230         this.request.addHeader("content-type", "application/json-rpc");
231 
232         JSONInterceptor interceptor = new JSONInterceptor();
233         interceptor.setEnableSMD(true);
234         SMDActionTest2 action = new SMDActionTest2();
235 
236         this.invocation.setAction(action);
237 
238         // can't be invoked
239         interceptor.intercept(this.invocation);
240         assertFalse(this.invocation.isInvoked());
241 
242         String json = response.getContentAsString();
243 
244         String normalizedActual = TestUtils.normalize(json, true);
245         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("smd-12.txt"));
246         assertEquals(normalizedExpected, normalizedActual);
247 
248         assertEquals("application/json-rpc;charset=ISO-8859-1", response.getContentType());
249     }
250 
251     @SuppressWarnings("unchecked")
252     public void testSMDObjectsNoResult() throws Exception {
253         // request
254         setRequestContent("smd-7.txt");
255         this.request.addHeader("content-type", "application/json-rpc");
256 
257         JSONInterceptor interceptor = new JSONInterceptor();
258         interceptor.setEnableSMD(true);
259         SMDActionTest1 action = new SMDActionTest1();
260 
261         this.invocation.setAction(action);
262 
263         // can't be invoked
264         interceptor.intercept(this.invocation);
265         assertFalse(this.invocation.isInvoked());
266 
267         // asert values were passed properly
268         Bean bean = action.getBeanParam();
269         assertNotNull(bean);
270         assertTrue(bean.isBooleanField());
271         assertEquals(bean.getStringField(), "test");
272         assertEquals(bean.getIntField(), 10);
273         assertEquals(bean.getCharField(), 's');
274         assertEquals(bean.getDoubleField(), 10.1);
275         assertEquals(bean.getByteField(), 3);
276 
277         List list = action.getListParam();
278         assertNotNull(list);
279         assertEquals("str0", list.get(0));
280         assertEquals("str1", list.get(1));
281 
282         Map map = action.getMapParam();
283         assertNotNull(map);
284         assertNotNull(map.get("a"));
285         assertEquals(new Long(1), map.get("a"));
286         assertNotNull(map.get("c"));
287         List insideList = (List) map.get("c");
288         assertEquals(1.0d, insideList.get(0));
289         assertEquals(2.0d, insideList.get(1));
290 
291         String json = response.getContentAsString();
292         String normalizedActual = TestUtils.normalize(json, true);
293         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("smd-11.txt"));
294         assertEquals(normalizedExpected, normalizedActual);
295 
296         assertEquals("application/json-rpc;charset=ISO-8859-1", response.getContentType());
297     }
298 
299     @SuppressWarnings( { "unchecked", "unchecked" })
300     public void testReadEmpty() throws Exception {
301         // request
302         setRequestContent("json-6.txt");
303         this.request.addHeader("content-type", "application/json");
304 
305         // interceptor
306         JSONInterceptor interceptor = new JSONInterceptor();
307         TestAction action = new TestAction();
308 
309         this.invocation.setAction(action);
310 
311         interceptor.intercept(this.invocation);
312     }
313 
314     @SuppressWarnings( { "unchecked", "unchecked" })
315     public void test() throws Exception {
316         // request
317         setRequestContent("json-1.txt");
318         this.request.addHeader("content-type", "application/json");
319 
320         // interceptor
321         JSONInterceptor interceptor = new JSONInterceptor();
322         TestAction action = new TestAction();
323 
324         this.invocation.setAction(action);
325 
326         interceptor.intercept(this.invocation);
327 
328         // serialize and compare
329         List list = action.getList();
330 
331         assertNotNull(list);
332         assertEquals(list.size(), 10);
333 
334         list = action.getCollection();
335         assertNotNull(list);
336         assertEquals(list.size(), 3);
337         assertEquals(list.get(0), "b");
338         assertEquals(list.get(1), 1L);
339         list = (List) list.get(2);
340         assertNotNull(list);
341         assertEquals(list.size(), 2);
342         assertEquals(list.get(0), 10L);
343         assertEquals(list.get(1), 12L);
344 
345         list = action.getCollection2();
346         assertNotNull(list);
347         assertEquals(list.size(), 1);
348 
349         // inside a map any primitive is either: String, Long, Boolean or Double
350         Map bean = (Map) list.get(0);
351 
352         assertNotNull(bean);
353         assertTrue((Boolean) bean.get("booleanField"));
354         assertEquals(bean.get("charField"), "s");
355         assertEquals(bean.get("doubleField"), 10.1);
356         assertEquals(bean.get("floatField"), 1.5);
357         assertEquals(bean.get("intField"), 10L);
358         assertEquals(bean.get("longField"), 100L);
359         assertEquals(bean.get("stringField"), "str");
360 
361         bean = (Map) bean.get("objectField");
362         assertNotNull(bean);
363         assertFalse((Boolean) bean.get("booleanField"));
364         assertEquals(bean.get("charField"), "\u0000");
365         assertEquals(bean.get("doubleField"), 2.2);
366         assertEquals(bean.get("floatField"), 1.1);
367         assertEquals(bean.get("intField"), 0L);
368         assertEquals(bean.get("longField"), 0L);
369         assertEquals(bean.get("stringField"), "  ");
370 
371         assertEquals(action.getFoo(), "foo");
372 
373         Map map = action.getMap();
374 
375         assertNotNull(map);
376         assertEquals(map.size(), 2);
377         assertEquals(map.get("a"), 1L);
378         list = (List) map.get("c");
379         assertNotNull(list);
380         assertEquals(list.size(), 2);
381         assertEquals(list.get(0), 1.0);
382         assertEquals(list.get(1), 2.0);
383 
384         assertEquals(action.getResult(), null);
385 
386         Bean bean2 = action.getBean();
387 
388         assertNotNull(bean2);
389         assertTrue(bean2.isBooleanField());
390         assertEquals(bean2.getStringField(), "test");
391         assertEquals(bean2.getIntField(), 10);
392         assertEquals(bean2.getCharField(), 's');
393         assertEquals(bean2.getDoubleField(), 10.1);
394         assertEquals(bean2.getByteField(), 3);
395 
396         String[] strArray = action.getArray();
397 
398         assertNotNull(strArray);
399         assertEquals(strArray.length, 2);
400         assertEquals(strArray[0], "str0");
401         assertEquals(strArray[1], "str1");
402 
403         int[] intArray = action.getIntArray();
404 
405         assertNotNull(intArray);
406         assertEquals(intArray.length, 2);
407         assertEquals(intArray[0], 1);
408         assertEquals(intArray[1], 2);
409 
410         Bean[] beanArray = action.getBeanArray();
411 
412         assertNotNull(beanArray);
413         assertNotNull(beanArray[0]);
414         assertEquals(beanArray[0].getStringField(), "bean1");
415         assertNotNull(beanArray[1]);
416         assertEquals(beanArray[1].getStringField(), "bean2");
417 
418         Calendar calendar = Calendar.getInstance();
419         calendar.setTime(action.getDate());
420 
421         assertEquals(calendar.get(Calendar.YEAR), 1999);
422         assertEquals(calendar.get(Calendar.MONTH), Calendar.DECEMBER);
423         assertEquals(calendar.get(Calendar.DAY_OF_MONTH), 31);
424         assertEquals(calendar.get(Calendar.HOUR), 11);
425         assertEquals(calendar.get(Calendar.MINUTE), 59);
426         assertEquals(calendar.get(Calendar.SECOND), 59);
427 
428         calendar.setTime(action.getDate2());
429         assertEquals(calendar.get(Calendar.YEAR), 1999);
430         assertEquals(calendar.get(Calendar.MONTH), Calendar.DECEMBER);
431         assertEquals(calendar.get(Calendar.DAY_OF_MONTH), 31);
432 
433         // test desrialize=false
434         assertNull(action.getFoo2());
435     }
436 
437     public void testRoot() throws Exception {
438         setRequestContent("json-5.txt");
439         this.request.addHeader("content-type", "application/json");
440 
441         // interceptor
442         JSONInterceptor interceptor = new JSONInterceptor();
443         interceptor.setRoot("bean");
444         TestAction4 action = new TestAction4();
445 
446         this.invocation.setAction(action);
447         this.invocation.getStack().push(action);
448 
449         interceptor.intercept(this.invocation);
450 
451         Bean bean2 = action.getBean();
452 
453         assertNotNull(bean2);
454         assertTrue(bean2.isBooleanField());
455         assertEquals(bean2.getStringField(), "test");
456         assertEquals(bean2.getIntField(), 10);
457         assertEquals(bean2.getCharField(), 's');
458         assertEquals(bean2.getDoubleField(), 10.1);
459         assertEquals(bean2.getByteField(), 3);
460     }
461 
462     @Override
463     protected void setUp() throws Exception {
464         super.setUp();
465 
466         this.request = new MockHttpServletRequest();
467         this.response = new MockHttpServletResponse();
468 
469         ActionContext context = ActionContext.getContext();
470         ValueStack stack = context.getValueStack();
471 
472         ActionContext.setContext(context);
473         context.put(StrutsStatics.HTTP_REQUEST, this.request);
474         context.put(StrutsStatics.HTTP_RESPONSE, this.response);
475 
476         MockServletContext servletContext = new MockServletContext();
477 
478         context.put(StrutsStatics.SERVLET_CONTEXT, servletContext);
479         this.invocation = new MockActionInvocationEx();
480         this.invocation.setInvocationContext(context);
481         this.invocation.setStack(stack);
482     }
483 }
484 
485 class MockActionInvocationEx extends MockActionInvocation {
486     private boolean invoked;
487 
488     @Override
489     public String invoke() throws Exception {
490         this.invoked = true;
491         return super.invoke();
492     }
493 
494     public boolean isInvoked() {
495         return this.invoked;
496     }
497 
498     public void setInvoked(boolean invoked) {
499         this.invoked = invoked;
500     }
501 
502 }