View Javadoc

1   /*
2    + * $Id: JSONResultTest.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.math.BigDecimal;
24  import java.math.BigInteger;
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  import java.util.Calendar;
28  import java.util.Date;
29  import java.util.HashMap;
30  import java.util.LinkedHashMap;
31  import java.util.List;
32  import java.util.Map;
33  import java.util.regex.Pattern;
34  
35  import javax.servlet.http.HttpServletResponse;
36  
37  import org.apache.struts2.StrutsStatics;
38  import org.apache.struts2.StrutsTestCase;
39  import org.springframework.mock.web.MockHttpServletRequest;
40  import org.springframework.mock.web.MockHttpServletResponse;
41  import org.springframework.mock.web.MockServletContext;
42  
43  import com.opensymphony.xwork2.ActionContext;
44  import com.opensymphony.xwork2.mock.MockActionInvocation;
45  import com.opensymphony.xwork2.util.ValueStack;
46  
47  /***
48   * JSONResultTest
49   */
50  public class JSONResultTest extends StrutsTestCase {
51      MockActionInvocation invocation;
52      MockHttpServletResponse response;
53      MockServletContext servletContext;
54      ActionContext context;
55      ValueStack stack;
56      MockHttpServletRequest request;
57  
58      public void testJSONUtilNPEOnNullMehtod() {
59          Map map = new HashMap();
60          map.put("createtime", new Date());
61          try {
62              JSONUtil.serialize(map);
63          } catch (JSONException e) {
64              fail(e.getMessage());
65          }
66      }
67  
68      public void testJSONWriterEndlessLoopOnExludedProperties() throws JSONException {
69          Pattern all = Pattern.compile(".*");
70  
71          JSONWriter writer = new JSONWriter();
72          writer.write(Arrays.asList("a", "b"), Arrays.asList(all), null, false);
73      }
74  
75      public void testSMDDisabledSMD() throws Exception {
76          JSONResult result = new JSONResult();
77          SMDActionTest1 action = new SMDActionTest1();
78  
79          this.invocation.setAction(action);
80          result.execute(this.invocation);
81  
82          String smd = response.getContentAsString();
83  
84          String normalizedActual = TestUtils.normalize(smd, true);
85          String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("smd-8.txt"));
86          assertEquals(normalizedExpected, normalizedActual);
87      }
88  
89      public void testSMDDefault() throws Exception {
90          JSONResult result = new JSONResult();
91          result.setEnableSMD(true);
92          SMDActionTest1 action = new SMDActionTest1();
93  
94          this.invocation.setAction(action);
95          result.execute(this.invocation);
96  
97          String smd = response.getContentAsString();
98  
99          String normalizedActual = TestUtils.normalize(smd, true);
100         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("smd-1.txt"));
101         assertEquals(normalizedExpected, normalizedActual);
102         assertEquals("application/json;charset=ISO-8859-1", response.getContentType());
103     }
104 
105     public void testSMDDefaultAnnotations() throws Exception {
106         JSONResult result = new JSONResult();
107         result.setEnableSMD(true);
108         SMDActionTest2 action = new SMDActionTest2();
109 
110         this.invocation.setAction(action);
111         result.execute(this.invocation);
112 
113         String smd = response.getContentAsString();
114 
115         String normalizedActual = TestUtils.normalize(smd, true);
116         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("smd-2.txt"));
117         assertEquals(normalizedExpected, normalizedActual);
118         assertEquals("application/json;charset=ISO-8859-1", response.getContentType());
119     }
120 
121     public void testExcludeNullPropeties() throws Exception {
122         JSONResult result = new JSONResult();
123         result.setExcludeNullProperties(true);
124         TestAction action = new TestAction();
125         action.setFoo("fool");
126 
127         this.invocation.setAction(action);
128         result.execute(this.invocation);
129 
130         String smd = response.getContentAsString();
131 
132         String normalizedActual = TestUtils.normalize(smd, true);
133         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("nulls-1.txt"));
134         assertEquals(normalizedExpected, normalizedActual);
135     }
136 
137     public void testWrapPrefix() throws Exception {
138         JSONResult result = new JSONResult();
139         result.setWrapPrefix("_prefix_");
140         TestAction2 action = new TestAction2();
141 
142         this.invocation.setAction(action);
143         result.execute(this.invocation);
144 
145         String out = response.getContentAsString();
146 
147         String normalizedActual = TestUtils.normalize(out, true);
148         String normalizedExpected = "_prefix_{\"name\":\"name\"}";
149         assertEquals(normalizedExpected, normalizedActual);
150     }
151 
152     public void testSuffix() throws Exception {
153         JSONResult result = new JSONResult();
154         result.setWrapSuffix("_suffix_");
155         TestAction2 action = new TestAction2();
156 
157         this.invocation.setAction(action);
158         result.execute(this.invocation);
159 
160         String out = response.getContentAsString();
161 
162         String normalizedActual = TestUtils.normalize(out, true);
163         String normalizedExpected = "{\"name\":\"name\"}_suffix_";
164         assertEquals(normalizedExpected, normalizedActual);
165     }
166 
167     public void testPrefixAndSuffix() throws Exception {
168         JSONResult result = new JSONResult();
169         result.setWrapPrefix("_prefix_");
170         result.setWrapSuffix("_suffix_");
171         TestAction2 action = new TestAction2();
172 
173         this.invocation.setAction(action);
174         result.execute(this.invocation);
175 
176         String out = response.getContentAsString();
177 
178         String normalizedActual = TestUtils.normalize(out, true);
179         String normalizedExpected = "_prefix_{\"name\":\"name\"}_suffix_";
180         assertEquals(normalizedExpected, normalizedActual);
181     }
182 
183     public void testPrefix() throws Exception {
184         JSONResult result = new JSONResult();
185         result.setExcludeNullProperties(true);
186         result.setPrefix(true);
187         TestAction action = new TestAction();
188         action.setFoo("fool");
189 
190         this.invocation.setAction(action);
191         result.execute(this.invocation);
192 
193         String smd = response.getContentAsString();
194 
195         String normalizedActual = TestUtils.normalize(smd, true);
196         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("prefix-1.txt"));
197         assertEquals(normalizedExpected, normalizedActual);
198     }
199 
200     @SuppressWarnings("unchecked")
201     public void test() throws Exception {
202         JSONResult result = new JSONResult();
203 
204         TestAction action = new TestAction();
205 
206         // test scape characters
207         action.setArray(new String[] { "a", "a", "\"", "//", "/", "\b", "\f", "\n", "\r", "\t" });
208 
209         List list = new ArrayList();
210 
211         list.add("b");
212         list.add(1);
213         list.add(new int[] { 10, 12 });
214         action.setCollection(list);
215 
216         // beans
217         List collection2 = new ArrayList();
218         Bean bean1 = new Bean();
219 
220         bean1.setBigDecimal(new BigDecimal("111111.111111"));
221         bean1.setBigInteger(new BigInteger("111111111111"));
222         bean1.setStringField("str");
223         bean1.setBooleanField(true);
224         bean1.setCharField('s');
225         bean1.setDoubleField(10.1);
226         bean1.setFloatField(1.5f);
227         bean1.setIntField(10);
228         bean1.setLongField(100);
229         bean1.setEnumField(AnEnum.ValueA);
230         bean1.setEnumBean(AnEnumBean.One);
231 
232         Bean bean2 = new Bean();
233 
234         bean2.setStringField("  ");
235         bean2.setBooleanField(false);
236         bean2.setFloatField(1.1f);
237         bean2.setDoubleField(2.2);
238         bean2.setEnumField(AnEnum.ValueB);
239         bean2.setEnumBean(AnEnumBean.Two);
240 
241         // circular reference
242         bean1.setObjectField(bean2);
243         bean2.setObjectField(bean1);
244 
245         collection2.add(bean1);
246         action.setCollection2(collection2);
247 
248         // keep order in map
249         Map map = new LinkedHashMap();
250 
251         map.put("a", 1);
252         map.put("c", new float[] { 1.0f, 2.0f });
253         action.setMap(map);
254 
255         action.setFoo("foo");
256         // should be ignored, marked 'transient'
257         action.setBar("bar");
258 
259         // date
260         Calendar calendar = Calendar.getInstance();
261         calendar.set(Calendar.YEAR, 1999);
262         calendar.set(Calendar.MONTH, Calendar.DECEMBER);
263         calendar.set(Calendar.DAY_OF_MONTH, 31);
264         calendar.set(Calendar.HOUR_OF_DAY, 11);
265         calendar.set(Calendar.MINUTE, 59);
266         calendar.set(Calendar.SECOND, 59);
267         action.setDate(calendar.getTime());
268         action.setDate2(calendar.getTime());
269 
270         this.invocation.setAction(action);
271         result.execute(this.invocation);
272 
273         String json = response.getContentAsString();
274 
275         String normalizedActual = TestUtils.normalize(json, true);
276         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json.txt"));
277         assertEquals(normalizedExpected, normalizedActual);
278         assertEquals("application/json;charset=ISO-8859-1", response.getContentType());
279     }
280 
281     @SuppressWarnings("unchecked")
282     public void testHierarchy() throws Exception {
283         JSONResult result = new JSONResult();
284         result.setIgnoreHierarchy(false);
285 
286         TestAction3 action = new TestAction3();
287         this.invocation.setAction(action);
288         result.execute(this.invocation);
289 
290         String json = response.getContentAsString();
291         String normalizedActual = TestUtils.normalize(json, true);
292         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json-4.txt"));
293         assertEquals(normalizedExpected, normalizedActual);
294         assertEquals("application/json;charset=ISO-8859-1", response.getContentType());
295     }
296 
297     @SuppressWarnings("unchecked")
298     public void testCommentWrap() throws Exception {
299         JSONResult result = new JSONResult();
300 
301         TestAction action = new TestAction();
302 
303         // test scape characters
304         action.setArray(new String[] { "a", "a", "\"", "//", "/", "\b", "\f", "\n", "\r", "\t" });
305 
306         List list = new ArrayList();
307 
308         list.add("b");
309         list.add(1);
310         list.add(new int[] { 10, 12 });
311         action.setCollection(list);
312 
313         // beans
314         List collection2 = new ArrayList();
315         Bean bean1 = new Bean();
316 
317         bean1.setStringField("str");
318         bean1.setBooleanField(true);
319         bean1.setCharField('s');
320         bean1.setDoubleField(10.1);
321         bean1.setFloatField(1.5f);
322         bean1.setIntField(10);
323         bean1.setLongField(100);
324         bean1.setEnumField(null);
325         bean1.setEnumBean(null);
326 
327         Bean bean2 = new Bean();
328 
329         bean2.setStringField("  ");
330         bean2.setBooleanField(false);
331         bean2.setFloatField(1.1f);
332         bean2.setDoubleField(2.2);
333         bean2.setEnumField(AnEnum.ValueC);
334         bean2.setEnumBean(AnEnumBean.Three);
335 
336         // circular reference
337         bean1.setObjectField(bean2);
338         bean2.setObjectField(bean1);
339 
340         collection2.add(bean1);
341         action.setCollection2(collection2);
342 
343         // keep order in map
344         Map map = new LinkedHashMap();
345 
346         map.put("a", 1);
347         map.put("c", new float[] { 1.0f, 2.0f });
348         action.setMap(map);
349 
350         action.setFoo("foo");
351         // should be ignored, marked 'transient'
352         action.setBar("bar");
353 
354         // date
355         Calendar calendar = Calendar.getInstance();
356         calendar.set(Calendar.YEAR, 1999);
357         calendar.set(Calendar.MONTH, Calendar.DECEMBER);
358         calendar.set(Calendar.DAY_OF_MONTH, 31);
359         calendar.set(Calendar.HOUR_OF_DAY, 11);
360         calendar.set(Calendar.MINUTE, 59);
361         calendar.set(Calendar.SECOND, 59);
362         action.setDate(calendar.getTime());
363         action.setDate2(calendar.getTime());
364 
365         this.invocation.setAction(action);
366         result.setWrapWithComments(true);
367         result.execute(this.invocation);
368 
369         String json = response.getContentAsString();
370 
371         String normalizedActual = TestUtils.normalize(json, true);
372         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json-3.txt"));
373         assertEquals(normalizedExpected, normalizedActual);
374         assertEquals("application/json;charset=ISO-8859-1", response.getContentType());
375     }
376 
377     private void executeTest2Action(JSONResult result) throws Exception {
378         TestAction action = new TestAction();
379 
380         // beans
381         Bean bean1 = new Bean();
382 
383         bean1.setStringField("str");
384         bean1.setBooleanField(true);
385         bean1.setCharField('s');
386         bean1.setDoubleField(10.1);
387         bean1.setFloatField(1.5f);
388         bean1.setIntField(10);
389         bean1.setLongField(100);
390         bean1.setEnumField(AnEnum.ValueA);
391         bean1.setEnumBean(AnEnumBean.One);
392 
393         // set root
394         action.setBean(bean1);
395         result.setRoot("bean");
396 
397         stack.push(action);
398         this.invocation.setStack(stack);
399         this.invocation.setAction(action);
400 
401         result.execute(this.invocation);
402     }
403 
404     public void test2() throws Exception {
405         JSONResult result = new JSONResult();
406 
407         executeTest2Action(result);
408         String json = response.getContentAsString();
409 
410         String normalizedActual = TestUtils.normalize(json, true);
411         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json-2.txt"));
412         assertEquals(normalizedExpected, normalizedActual);
413         assertEquals("application/json;charset=ISO-8859-1", response.getContentType());
414     }
415 
416     public void testJSONP() throws Exception {
417         JSONResult result = new JSONResult();
418         result.setCallbackParameter("callback");
419         request.addParameter("callback", "exec");
420 
421         executeTest2Action(result);
422         String json = response.getContentAsString();
423 
424         String normalizedActual = TestUtils.normalize(json, true);
425         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("jsonp-1.txt"));
426         assertEquals(normalizedExpected, normalizedActual);
427         assertEquals("application/json;charset=ISO-8859-1", response.getContentType());
428     }
429 
430     public void testNoCache() throws Exception {
431         JSONResult result = new JSONResult();
432         result.setNoCache(true);
433 
434         executeTest2Action(result);
435 
436         assertEquals("no-cache", response.getHeader("Cache-Control"));
437         assertEquals("0", response.getHeader("Expires"));
438         assertEquals("No-cache", response.getHeader("Pragma"));
439     }
440 
441     public void testContentType() throws Exception {
442         JSONResult result = new JSONResult();
443         result.setContentType("some_super_content");
444 
445         executeTest2Action(result);
446 
447         assertEquals("some_super_content;charset=ISO-8859-1", response.getContentType());
448     }
449 
450     public void testStatusCode() throws Exception {
451         JSONResult result = new JSONResult();
452         result.setStatusCode(HttpServletResponse.SC_CONTINUE);
453 
454         executeTest2Action(result);
455 
456         assertEquals(HttpServletResponse.SC_CONTINUE, response.getStatus());
457     }
458 
459     /***
460      * Repeats test2 but with the Enum serialized as a bean
461      */
462     public void test2WithEnumBean() throws Exception {
463         JSONResult result = new JSONResult();
464         result.setEnumAsBean(true);
465 
466         executeTest2Action(result);
467 
468         String json = response.getContentAsString();
469 
470         String normalizedActual = TestUtils.normalize(json, true);
471         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json-2-enum.txt"));
472         assertEquals(normalizedExpected, normalizedActual);
473         assertEquals("application/json;charset=ISO-8859-1", response.getContentType());
474     }
475 
476     /***
477      * Ensures that properties of given root object are read as shallow
478      * (non-recursive) unless specifically included.
479      */
480     public void testIncludeProperties() throws Exception {
481         JSONResult result = new JSONResult();
482         result.setIncludeProperties("foo");
483         TestAction action = new TestAction();
484         action.setFoo("fooValue");
485         action.setBean(new Bean());
486         this.invocation.setAction(action);
487         result.execute(this.invocation);
488 
489         String json = response.getContentAsString();
490         String normalizedActual = TestUtils.normalize(json, true);
491         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json-9.txt"));
492         assertEquals(normalizedExpected, normalizedActual);
493         assertEquals("application/json;charset=ISO-8859-1", response.getContentType());
494     }
495 
496     public void testIncludePropertiesWithList() throws Exception {
497         JSONResult result = new JSONResult();
498         result.setIncludeProperties("^list//[//d+//]//.booleanField");
499         TestAction action = new TestAction();
500 
501         List list = new ArrayList();
502 
503         list.add(new Bean());
504         list.add(new Bean());
505         list.add(new Bean());
506 
507         action.setList(list);
508 
509         this.invocation.setAction(action);
510         result.execute(this.invocation);
511 
512         String json = response.getContentAsString();
513         String normalizedActual = TestUtils.normalize(json, true);
514         String normalizedExpected = TestUtils.normalize(JSONResultTest.class.getResource("json-10.txt"));
515         assertEquals(normalizedExpected, normalizedActual);
516         assertEquals("application/json;charset=ISO-8859-1", response.getContentType());
517     }
518 
519     @Override
520     protected void setUp() throws Exception {
521         super.setUp();
522         this.response = new MockHttpServletResponse();
523         this.request = new MockHttpServletRequest();
524         this.request.setRequestURI("http://sumeruri");
525         this.context = ActionContext.getContext();
526         this.context.put(StrutsStatics.HTTP_RESPONSE, this.response);
527         this.context.put(StrutsStatics.HTTP_REQUEST, this.request);
528         this.stack = context.getValueStack();
529         this.servletContext = new MockServletContext();
530         this.context.put(StrutsStatics.SERVLET_CONTEXT, this.servletContext);
531         this.invocation = new MockActionInvocation();
532         this.invocation.setInvocationContext(this.context);
533     }
534 }