1   package org.apache.velocity.test;
2   
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  
22  import java.lang.reflect.Array;
23  import java.util.Arrays;
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  /**
28   * Used to check that method calls on Array references work properly
29   * and that they produce the same results as the same methods would on
30   * a fixed-size {@link List}.
31   */
32  public class ArrayMethodsTestCase extends BaseTestCase
33  {
34      public ArrayMethodsTestCase(final String name)
35      {
36          super(name);
37      }
38  
39      /**
40       * Runs the test.
41       */
42      public void testArrayMethods() throws Exception
43      {
44          // test an array of string objects
45          Object array = new String[] { "foo", "bar", "baz" };
46          checkResults(array, "woogie", true);
47  
48          // test an array of primitive ints
49          array = new int[] { 1, 3, 7 };
50          checkResults(array, new Integer(11), false);
51  
52          // test an array of mixed objects, including null
53          array = new Object[] { new Double(2.2), null };
54          checkResults(array, "whatever", true);
55          // then set all the values to null
56          checkResults(array, null, true);
57  
58          // then try an empty array
59          array = new Object[] {};
60          checkResults(array, null, true);
61  
62          // while we have an empty array and list in the context,
63          // make sure $array.get(0) and $list.get(0) throw
64          // the same type of exception (MethodInvocationException)
65          Throwable lt = null;
66          Throwable at = null;
67          try
68          {
69              evaluate("$list.get(0)");
70          }
71          catch (Throwable t)
72          {
73              lt = t;
74          }
75          try
76          {
77              evaluate("$array.get(0)");
78          }
79          catch (Throwable t)
80          {
81              at = t;
82          }
83          assertEquals(lt.getClass(), at.getClass());
84      }
85  
86      private void checkResults(Object array, Object setme,
87                                boolean compareToList) throws Exception
88      {
89          context.put("array", array);
90          if (compareToList)
91          {
92              // create a list to match...
93              context.put("list", new ArrayList(Arrays.asList((Object[])array)));
94          }
95  
96          // if the object to be set is null, then remove instead of put
97          if (setme != null)
98          {
99              context.put("setme", setme);
100         }
101         else
102         {
103             context.remove("setme");
104         }
105 
106         info("Changing to an array of: " + array.getClass().getComponentType());
107         info("Changing setme to: " + setme);
108 
109         int size = Array.getLength(array);
110         checkResult("size()", String.valueOf(size), compareToList);
111 
112         boolean isEmpty = (size == 0);
113         checkResult("isEmpty()", String.valueOf(isEmpty), compareToList);
114 
115         // check that the wrapping doesn't apply to java.lang.Object methods
116         // such as toString() (for backwards compatibility).
117         assertFalse(evaluate("$array").equals(evaluate("$list")));
118 
119         for (int i=0; i < size; i++)
120         {
121             // put the index in the context, so we can try
122             // both an explicit index and a reference index
123             context.put("index", new Integer(i));
124 
125             Object value = Array.get(array, i);
126             String get = "get($index)";
127             String set = "set("+i+", $setme)";
128             if (value == null)
129             {
130                 checkEmptyResult(get, compareToList);
131                 // set should return null
132                 checkEmptyResult(set, compareToList);
133             }
134             else
135             {
136                 checkResult(get, value.toString(), compareToList);
137                 // set should return the old get value
138                 checkResult(set, value.toString(), compareToList);
139             }
140 
141             // check that set() actually changed the value
142             assertEquals(setme, Array.get(array, i));
143 
144             // and check that get() now returns setme
145             if (setme == null)
146             {
147                 checkEmptyResult(get, compareToList);
148             }
149             else
150             {
151                 checkResult(get, setme.toString(), compareToList);
152 
153                 // now check that contains() properly finds the new value
154                 checkResult("contains($setme)", "true", compareToList);
155             }
156         }
157     }
158 
159     private void checkEmptyResult(String method, boolean compareToList)
160         throws Exception
161     {
162         checkResult(method, "", compareToList);
163     }
164 
165     private void checkResult(String method, String expected,
166                              boolean compareToList) throws Exception
167     {
168         String result = evaluate("$!array."+method);
169         assertEquals(expected, result);
170 
171         String listResult = null;
172         if (compareToList)
173         {
174             listResult = evaluate("$!list."+method);
175             assertEquals(result, listResult);
176         }
177 
178         info("    <$!array."+method+"> resolved to <"+result+">");
179         if (compareToList)
180         {
181             info("    <$!list."+method+"> resolved to "+listResult+">");
182         }
183     }
184 
185 }
186 
187