1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17import java.lang.reflect.InvocationTargetException;
18import java.lang.reflect.Method;
19
20// Note that $opt$ is a marker for the optimizing compiler to test
21// it does compile the method.
22
23public class Main extends TestCase {
24  public static void main(String[] args) throws Exception {
25    $opt$TestAllocations();
26    $opt$TestWithInitializations();
27    $opt$TestNegativeValueNewByteArray();
28    $opt$TestNegativeValueNewCharArray();
29    testNegativeArraySize();
30    testSmaliFilledNewArray();
31    testSmaliFillArrayData();
32    testSmaliVerifyError();
33  }
34
35  static void $opt$TestAllocations() {
36    float[] a = new float[1];
37    assertEquals(1, a.length);
38
39    double[] b = new double[2];
40    assertEquals(2, b.length);
41
42    long[] c = new long[3];
43    assertEquals(3, c.length);
44
45    int[] d = new int[4];
46    assertEquals(4, d.length);
47
48    short[] e = new short[5];
49    assertEquals(5, e.length);
50
51    char[] f = new char[6];
52    assertEquals(6, f.length);
53
54    byte[] g = new byte[7];
55    assertEquals(7, g.length);
56
57    boolean[] h = new boolean[8];
58    assertEquals(8, h.length);
59
60    Object[] i = new Object[9];
61    assertEquals(9, i.length);
62  }
63
64  static void $opt$TestWithInitializations() {
65    float[] a = { 1.2f };
66    assertEquals(1, a.length);
67    assertEquals(1.2f, a[0]);
68
69    double[] b = { 4.3, 1.2 };
70    assertEquals(2, b.length);
71    assertEquals(4.3, b[0]);
72    assertEquals(1.2, b[1]);
73
74    long[] c = { 4L, 5L };
75    assertEquals(2, c.length);
76    assertEquals(4L, c[0]);
77    assertEquals(5L, c[1]);
78
79    int[] d = {1, 2, 3};
80    assertEquals(3, d.length);
81    assertEquals(1, d[0]);
82    assertEquals(2, d[1]);
83    assertEquals(3, d[2]);
84
85    short[] e = {4, 5, 6};
86    assertEquals(3, e.length);
87    assertEquals(4, e[0]);
88    assertEquals(5, e[1]);
89    assertEquals(6, e[2]);
90
91    char[] f = {'a', 'b'};
92    assertEquals(2, f.length);
93    assertEquals('a', f[0]);
94    assertEquals('b', f[1]);
95
96    byte[] g = {7, 8, 9};
97    assertEquals(3, g.length);
98    assertEquals(7, g[0]);
99    assertEquals(8, g[1]);
100    assertEquals(9, g[2]);
101
102    boolean[] h = {true, false};
103    assertEquals(2, h.length);
104    assertEquals(true, h[0]);
105    assertEquals(false, h[1]);
106
107    Object obj1 = new Object();
108    Object obj2 = new Object();
109    Object[] i = {obj1, obj2};
110    assertEquals(2, i.length);
111    assertEquals(obj1, i[0]);
112    assertEquals(obj2, i[1]);
113  }
114
115  static void $opt$TestNegativeValueNewByteArray() {
116    // Use an array initializer to hint the use of filled-new-array.
117    byte[] a = { (byte)0xa0, (byte)0xa1, (byte)0xa2, (byte)0xa3,
118                 (byte)0xa4, (byte)0xa5, (byte)0xa6, (byte)0xa7 };
119    for (int i = 0; i < a.length; i++) {
120      assertEquals((byte)0xa0 + i, a[i]);
121    }
122  }
123
124  static void $opt$TestNegativeValueNewCharArray() {
125    // Use an array initializer to hint the use of filled-new-array.
126    char[] a = { (char)0xa000, (char)0xa001, (char)0xa002, (char)0xa003,
127                 (char)0xa004, (char)0xa005, (char)0xa006, (char)0xa007 };
128    for (int i = 0; i < a.length; i++) {
129      assertEquals((char)0xa000 + i, a[i]);
130    }
131  }
132
133  static void testNegativeArraySize() {
134    int i = 0;
135    try {
136      $opt$TestNegativeArraySize();
137    } catch (NegativeArraySizeException e) {
138      i = 1;
139    }
140    assertEquals(i, 1);
141  }
142
143  static int[] $opt$TestNegativeArraySize() {
144    int[] array = new int[-1];
145    return null;
146  }
147
148  public static void testSmaliFilledNewArray() throws Exception {
149    Class<?> c = Class.forName("FilledNewArray");
150
151    {
152      Method m = c.getMethod("newInt", Integer.TYPE, Integer.TYPE, Integer.TYPE);
153      Object[] args = {new Integer(1), new Integer(2), new Integer(3)};
154      int[] result = (int[])m.invoke(null, args);
155      assertEquals(3, result.length);
156      assertEquals(1, result[0]);
157      assertEquals(2, result[1]);
158      assertEquals(3, result[2]);
159    }
160
161    {
162      Method m = c.getMethod("newRef", Object.class, Object.class);
163      Object[] args = {new Integer(1), new Integer(2)};
164      Object[] result = (Object[])m.invoke(null, args);
165      assertEquals(2, result.length);
166      assertEquals(args[0], result[0]);
167      assertEquals(args[1], result[1]);
168    }
169
170    {
171      Method m = c.getMethod("newArray", int[].class, int[].class);
172      Object[] args = {new int[0], new int[1]};
173      Object[] result = (Object[])m.invoke(null, args);
174      assertEquals(2, result.length);
175      assertEquals(args[0], result[0]);
176      assertEquals(args[1], result[1]);
177    }
178
179    {
180      Method m = c.getMethod("newIntRange", Integer.TYPE, Integer.TYPE, Integer.TYPE);
181      Object[] args = {new Integer(1), new Integer(2), new Integer(3)};
182      int[] result = (int[])m.invoke(null, args);
183      assertEquals(3, result.length);
184      assertEquals(1, result[0]);
185      assertEquals(2, result[1]);
186      assertEquals(3, result[2]);
187    }
188
189    {
190      Method m = c.getMethod("newRefRange", Object.class, Object.class);
191      Object[] args = {new Integer(1), new Integer(2)};
192      Object[] result = (Object[])m.invoke(null, args);
193      assertEquals(2, result.length);
194      assertEquals(args[0], result[0]);
195      assertEquals(args[1], result[1]);
196    }
197
198    {
199      Method m = c.getMethod("newArrayRange", int[].class, int[].class);
200      Object[] args = {new int[0], new int[1]};
201      Object[] result = (Object[])m.invoke(null, args);
202      assertEquals(2, result.length);
203      assertEquals(args[0], result[0]);
204      assertEquals(args[1], result[1]);
205    }
206  }
207
208  public static void testSmaliVerifyError() throws Exception {
209    Error error = null;
210    // Ensure the elements in filled-new-array must be assignable
211    // to the array component type.
212    try {
213      Class.forName("FilledNewArrayVerifyError");
214    } catch (VerifyError e) {
215      error = e;
216    }
217    assertNotNull(error);
218  }
219
220  public static void testSmaliFillArrayData() throws Exception {
221    Class<?> c = Class.forName("FillArrayData");
222    {
223      Method m = c.getMethod("intArray", int[].class);
224      int[] array = new int[7];
225      Object[] args = { array };
226      m.invoke(null, args);
227      assertEquals(7, array.length);
228      assertEquals(1, array[0]);
229      assertEquals(2, array[1]);
230      assertEquals(3, array[2]);
231      assertEquals(4, array[3]);
232      assertEquals(5, array[4]);
233      assertEquals(0, array[5]);
234      assertEquals(0, array[6]);
235
236      array = new int[2];
237      args[0] = array;
238      Throwable exception  = null;
239      try {
240        m.invoke(null, args);
241      } catch (InvocationTargetException e) {
242        exception = e.getCause();
243        assertTrue(exception instanceof IndexOutOfBoundsException);
244      }
245      assertNotNull(exception);
246      exception = null;
247      // Test that nothing has been written to the array.
248      assertEquals(0, array[0]);
249      assertEquals(0, array[1]);
250
251      args[0] = null;
252      try {
253        m.invoke(null, args);
254      } catch (InvocationTargetException e) {
255        exception = e.getCause();
256        assertTrue(exception instanceof NullPointerException);
257      }
258      assertNotNull(exception);
259    }
260
261    {
262      Method m = c.getMethod("shortArray", short[].class);
263      short[] array = new short[7];
264      Object[] args = { array };
265      m.invoke(null, args);
266      assertEquals(7, array.length);
267      assertEquals(1, array[0]);
268      assertEquals(2, array[1]);
269      assertEquals(3, array[2]);
270      assertEquals(4, array[3]);
271      assertEquals(5, array[4]);
272      assertEquals(0, array[5]);
273      assertEquals(0, array[6]);
274
275      array = new short[2];
276      args[0] = array;
277      Throwable exception  = null;
278      try {
279        m.invoke(null, args);
280      } catch (InvocationTargetException e) {
281        exception = e.getCause();
282        assertTrue(exception instanceof IndexOutOfBoundsException);
283      }
284      assertNotNull(exception);
285      exception = null;
286      // Test that nothing has been written to the array.
287      assertEquals(0, array[0]);
288      assertEquals(0, array[1]);
289
290      args[0] = null;
291      try {
292        m.invoke(null, args);
293      } catch (InvocationTargetException e) {
294        exception = e.getCause();
295        assertTrue(exception instanceof NullPointerException);
296      }
297      assertNotNull(exception);
298    }
299
300    {
301      Method m = c.getMethod("longArray", long[].class);
302      long[] array = new long[7];
303      Object[] args = { array };
304      m.invoke(null, args);
305      assertEquals(7, array.length);
306      assertEquals(1L, array[0]);
307      assertEquals(2L, array[1]);
308      assertEquals(3L, array[2]);
309      assertEquals(4L, array[3]);
310      assertEquals(5L, array[4]);
311      assertEquals(0L, array[5]);
312      assertEquals(0L, array[6]);
313
314      array = new long[2];
315      args[0] = array;
316      Throwable exception  = null;
317      try {
318        m.invoke(null, args);
319      } catch (InvocationTargetException e) {
320        exception = e.getCause();
321        assertTrue(exception instanceof IndexOutOfBoundsException);
322      }
323      assertNotNull(exception);
324      exception = null;
325      // Test that nothing has been written to the array.
326      assertEquals(0, array[0]);
327      assertEquals(0, array[1]);
328
329      args[0] = null;
330      try {
331        m.invoke(null, args);
332      } catch (InvocationTargetException e) {
333        exception = e.getCause();
334        assertTrue(exception instanceof NullPointerException);
335      }
336      assertNotNull(exception);
337    }
338
339    {
340      Method m = c.getMethod("charArray", char[].class);
341      char[] array = new char[7];
342      Object[] args = { array };
343      m.invoke(null, args);
344      assertEquals(7, array.length);
345      assertEquals(1, array[0]);
346      assertEquals(2, array[1]);
347      assertEquals(3, array[2]);
348      assertEquals(4, array[3]);
349      assertEquals(5, array[4]);
350      assertEquals(0, array[5]);
351      assertEquals(0, array[6]);
352
353      array = new char[2];
354      args[0] = array;
355      Throwable exception  = null;
356      try {
357        m.invoke(null, args);
358      } catch (InvocationTargetException e) {
359        exception = e.getCause();
360        assertTrue(exception instanceof IndexOutOfBoundsException);
361      }
362      assertNotNull(exception);
363      exception = null;
364      // Test that nothing has been written to the array.
365      assertEquals(0, array[0]);
366      assertEquals(0, array[1]);
367
368      args[0] = null;
369      try {
370        m.invoke(null, args);
371      } catch (InvocationTargetException e) {
372        exception = e.getCause();
373        assertTrue(exception instanceof NullPointerException);
374      }
375      assertNotNull(exception);
376    }
377
378    {
379      Method m = c.getMethod("byteArray", byte[].class);
380      byte[] array = new byte[7];
381      Object[] args = { array };
382      m.invoke(null, args);
383      assertEquals(7, array.length);
384      assertEquals(1, array[0]);
385      assertEquals(2, array[1]);
386      assertEquals(3, array[2]);
387      assertEquals(4, array[3]);
388      assertEquals(5, array[4]);
389      assertEquals(0, array[5]);
390      assertEquals(0, array[6]);
391
392      array = new byte[2];
393      args[0] = array;
394      Throwable exception  = null;
395      try {
396        m.invoke(null, args);
397      } catch (InvocationTargetException e) {
398        exception = e.getCause();
399        assertTrue(exception instanceof IndexOutOfBoundsException);
400      }
401      assertNotNull(exception);
402      exception = null;
403      // Test that nothing has been written to the array.
404      assertEquals(0, array[0]);
405      assertEquals(0, array[1]);
406
407      args[0] = null;
408      try {
409        m.invoke(null, args);
410      } catch (InvocationTargetException e) {
411        exception = e.getCause();
412        assertTrue(exception instanceof NullPointerException);
413      }
414      assertNotNull(exception);
415    }
416
417    {
418      Method m = c.getMethod("booleanArray", boolean[].class);
419      boolean[] array = new boolean[5];
420      Object[] args = { array };
421      m.invoke(null, args);
422      assertEquals(5, array.length);
423      assertEquals(false, array[0]);
424      assertEquals(true, array[1]);
425      assertEquals(true, array[2]);
426      assertEquals(false, array[3]);
427      assertEquals(false, array[4]);
428
429      array = new boolean[2];
430      args[0] = array;
431      Throwable exception  = null;
432      try {
433        m.invoke(null, args);
434      } catch (InvocationTargetException e) {
435        exception = e.getCause();
436        assertTrue(exception instanceof IndexOutOfBoundsException);
437      }
438      assertNotNull(exception);
439      exception = null;
440      // Test that nothing has been written to the array.
441      assertEquals(false, array[0]);
442      assertEquals(false, array[1]);
443
444      args[0] = null;
445      try {
446        m.invoke(null, args);
447      } catch (InvocationTargetException e) {
448        exception = e.getCause();
449        assertTrue(exception instanceof NullPointerException);
450      }
451      assertNotNull(exception);
452    }
453  }
454}
455