xref: /aosp_15_r20/art/test/201-built-in-except-detail-messages/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1 /*
2  * Copyright (C) 2012 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 
17 import java.lang.reflect.Array;
18 import java.lang.reflect.Field;
19 import java.lang.reflect.Method;
20 
21 public class Main {
main(String[] args)22   public static void main(String[] args) throws Exception {
23     arrayAccess();
24     arrayStore();
25     classCast();
26     classNotFound();
27     negativeArraySize();
28     nullPointers();
29     reflection();
30     stringIndex();
31   }
32 
assertEquals(String expected, String actual)33   private static void assertEquals(String expected, String actual) {
34     if (expected == null && actual == null) {
35       return;
36     }
37     if (expected != null && expected.equals(actual)) {
38       return;
39     }
40     throw new AssertionError("not equal\n" +
41                                  "expected: " + expected + "\n" +
42                                  "actual:   " + actual);
43   }
44 
fail()45   private static void fail() {
46     throw new AssertionError();
47   }
48 
arrayAccess()49   private static void arrayAccess() throws Exception {
50     byte[] bs = new byte[1];
51     double[] ds = new double[1];
52     Object[] os = new Object[1];
53 
54     // aput
55     try {
56       bs[2] = 0;
57       fail();
58     } catch (ArrayIndexOutOfBoundsException ex) {
59       assertEquals("length=1; index=2", ex.getMessage());
60     }
61 
62     // aget
63     try {
64       byte b = bs[2];
65       fail();
66     } catch (ArrayIndexOutOfBoundsException ex) {
67       assertEquals("length=1; index=2", ex.getMessage());
68     }
69 
70     // aput-wide
71     try {
72       ds[2] = 0.0;
73       fail();
74     } catch (ArrayIndexOutOfBoundsException ex) {
75       assertEquals("length=1; index=2", ex.getMessage());
76     }
77 
78     // aget-wide
79     try {
80       double d = ds[2];
81       fail();
82     } catch (ArrayIndexOutOfBoundsException ex) {
83       assertEquals("length=1; index=2", ex.getMessage());
84     }
85 
86     // aput-object
87     try {
88       os[2] = null;
89       fail();
90     } catch (ArrayIndexOutOfBoundsException ex) {
91       assertEquals("length=1; index=2", ex.getMessage());
92     }
93 
94     // aget-object
95     try {
96       Object o = os[2];
97       fail();
98     } catch (ArrayIndexOutOfBoundsException ex) {
99       assertEquals("length=1; index=2", ex.getMessage());
100     }
101   }
102 
arrayStore()103   private static void arrayStore() throws Exception {
104     try {
105       Object[] array = new String[10];
106       Object o = new Exception();
107       array[0] = o;
108       fail();
109     } catch (ArrayStoreException ex) {
110       assertEquals("java.lang.Exception cannot be stored in an array of type java.lang.String[]",
111                    ex.getMessage());
112     }
113 
114     try {
115       Object[] array = new C[10][];
116       Object o = new Integer(5);
117       array[0] = o;
118       fail();
119     } catch (ArrayStoreException ex) {
120       assertEquals("java.lang.Integer cannot be stored in an array of type Main$C[][]",
121                    ex.getMessage());
122     }
123 
124     try {
125       Object[] array = new Float[10][];
126       Object o = new C[4];
127       array[0] = o;
128       fail();
129     } catch (ArrayStoreException ex) {
130       assertEquals("Main$C[] cannot be stored in an array of type java.lang.Float[][]",
131                    ex.getMessage());
132     }
133 
134     try {
135       String[] src = new String[] { null, null, null, null, "hello", "goodbye" };
136       Integer[] dst = new Integer[10];
137       System.arraycopy(src, 1, dst, 0, 5);
138     } catch (ArrayStoreException ex) {
139       assertEquals("source[4] of type java.lang.String cannot be stored in destination array of type java.lang.Integer[]",
140                    ex.getMessage());
141     }
142 
143     try {
144       String[] src = new String[1];
145       int[] dst = new int[1];
146       System.arraycopy(src, 0, dst, 0, 1);
147     } catch (ArrayStoreException ex) {
148       assertEquals("Incompatible types: src=java.lang.String[], dst=int[]", ex.getMessage());
149     }
150 
151     try {
152       float[] src = new float[1];
153       Runnable[] dst = new Runnable[1];
154       System.arraycopy(src, 0, dst, 0, 1);
155     } catch (ArrayStoreException ex) {
156       assertEquals("Incompatible types: src=float[], dst=java.lang.Runnable[]", ex.getMessage());
157     }
158 
159     try {
160       boolean[] src = new boolean[1];
161       double[][] dst = new double[1][];
162       System.arraycopy(src, 0, dst, 0, 1);
163     } catch (ArrayStoreException ex) {
164       assertEquals("Incompatible types: src=boolean[], dst=double[][]", ex.getMessage());
165     }
166 
167     try {
168       String src = "hello";
169       Object[] dst = new Object[1];
170       System.arraycopy(src, 0, dst, 0, 1);
171     } catch (ArrayStoreException ex) {
172       assertEquals("source of type java.lang.String is not an array", ex.getMessage());
173     }
174 
175     try {
176       Object[] src = new Object[1];
177       Integer dst = new Integer(5);
178       System.arraycopy(src, 0, dst, 0, 1);
179     } catch (ArrayStoreException ex) {
180       assertEquals("destination of type java.lang.Integer is not an array", ex.getMessage());
181     }
182 
183     // This test demonstrates that the exception message complains
184     // about the source in cases where neither source nor
185     // destination is an array.
186     try {
187       System.arraycopy(new C(), 0, "hello", 0, 1);
188     } catch (ArrayStoreException ex) {
189       assertEquals("source of type Main$C is not an array", ex.getMessage());
190     }
191   }
192 
classCast()193   private static void classCast() throws Exception {
194     // Reference types.
195     try {
196       Object o = new Exception();
197       String s = (String) o;
198       fail();
199     } catch (ClassCastException ex) {
200       assertEquals("java.lang.Exception cannot be cast to java.lang.String", ex.getMessage());
201     }
202 
203     // Arrays of reference types.
204     try {
205       Object o = (C) makeArray(String.class);
206       fail();
207     } catch (ClassCastException ex) {
208       assertEquals("java.lang.String[] cannot be cast to Main$C", ex.getMessage());
209     }
210 
211     // Arrays of primitives.
212     try {
213       Object o = (C) makeArray(float.class);
214       fail();
215     } catch (ClassCastException ex) {
216       assertEquals("float[] cannot be cast to Main$C", ex.getMessage());
217     }
218 
219     // Multi-dimensional arrays of primitives.
220     try {
221       Object o = (C) makeArray(char[].class);
222       fail();
223     } catch (ClassCastException ex) {
224       assertEquals("char[][] cannot be cast to Main$C", ex.getMessage());
225     }
226 
227     // Multi-dimensional arrays of references.
228     try {
229       Object o = (Object[][][]) makeInteger();
230       fail();
231     } catch (ClassCastException ex) {
232       assertEquals("java.lang.Integer cannot be cast to java.lang.Object[][][]", ex.getMessage());
233     }
234   }
235 
236   static class C { }
237 
238   /**
239    * Helper for testCastOperator and testCastOperatorWithArrays. It's important that the
240    * return type is Object, since otherwise the compiler will just reject the code.
241    */
makeInteger()242   private static Object makeInteger() {
243     return new Integer(5);
244   }
245 
246   /**
247    * Helper for testCastOperatorWithArrays. It's important that
248    * the return type is Object.
249    */
makeArray(Class<?> c)250   private static Object makeArray(Class<?> c) {
251     return Array.newInstance(c, 1);
252   }
253 
classNotFound()254   private static void classNotFound() throws Exception {
255     try {
256       // There is no such thing as an array of void.
257       Class.forName("[V");
258       fail();
259     } catch (ClassNotFoundException ex) {
260       assertEquals("Invalid name: [V", ex.getMessage());
261     }
262 
263     try {
264       // This class name is valid, but doesn't exist.
265       Class.forName("package.Class");
266       fail();
267     } catch (ClassNotFoundException ex) {
268       assertEquals("package.Class", ex.getMessage());
269     }
270 
271     try {
272       // This array class name is valid, but the type doesn't exist.
273       Class.forName("[[Lpackage.Class;");
274       fail();
275     } catch (ClassNotFoundException ex) {
276       assertEquals("[[Lpackage.Class;", ex.getMessage());
277     }
278   }
279 
negativeArraySize()280   private static void negativeArraySize() throws Exception {
281     try {
282       int[] is = new int[-123];
283       fail();
284     } catch (NegativeArraySizeException ex) {
285       assertEquals("-123", ex.getMessage());
286     }
287   }
288 
289   // Defeat the fact that null's are untyped for precise detail message creation with quickening.
returnNullObject()290   private static Object returnNullObject() {
291     return null;
292   }
293 
returnNullA()294   private static A returnNullA() {
295     return null;
296   }
297 
nullPointers()298   private static void nullPointers() throws Exception {
299     // Invoke method.
300     try {
301       Object o = returnNullObject();
302       o.hashCode();
303       fail();
304     } catch (NullPointerException ex) {
305       assertEquals("Attempt to invoke virtual method 'int java.lang.Object.hashCode()' on a null object reference", ex.getMessage());
306     }
307 
308     // Read field.
309     try {
310       A a = returnNullA();
311       int i = a.i;
312       fail();
313     } catch (NullPointerException ex) {
314       assertEquals(
315           "Attempt to read from field 'int A.i' on a null object reference in method 'void Main.nullPointers()'",
316           ex.getMessage());
317     }
318 
319     // Write field.
320     try {
321       A a = returnNullA();
322       a.i = 1;
323       fail();
324     } catch (NullPointerException ex) {
325       assertEquals(
326           "Attempt to write to field 'int A.i' on a null object reference in method 'void Main.nullPointers()'",
327           ex.getMessage());
328     }
329 
330     // Read array.
331     try {
332       int[] is = null;
333       int i = is[0];
334       fail();
335     } catch (NullPointerException ex) {
336       assertEquals("Attempt to read from null array", ex.getMessage());
337     }
338 
339     // Write array.
340     try {
341       int[] is = null;
342       is[0] = 1;
343       fail();
344     } catch (NullPointerException ex) {
345       assertEquals("Attempt to write to null array", ex.getMessage());
346     }
347 
348     // Array length.
349     try {
350       int[] is = null;
351       int i = is.length;
352       fail();
353     } catch (NullPointerException ex) {
354       assertEquals("Attempt to get length of null array", ex.getMessage());
355     }
356   }
357 
reflection()358   private static void reflection() throws Exception {
359     // Can't assign Integer to a String field.
360     try {
361       Field field = A.class.getField("b");
362       field.set(new A(), 5);
363       fail();
364     } catch (IllegalArgumentException expected) {
365       assertEquals("field A.b has type java.lang.String, got java.lang.Integer",
366           expected.getMessage());
367     }
368 
369     // Can't unbox null to a primitive.
370     try {
371       Field field = A.class.getField("i");
372       field.set(new A(), null);
373       fail();
374     } catch (IllegalArgumentException expected) {
375       assertEquals("field A.i has type int, got null", expected.getMessage());
376     }
377 
378     // Can't unbox String to a primitive.
379     try {
380       Field field = A.class.getField("i");
381       field.set(new A(), "hello, world!");
382       fail();
383     } catch (IllegalArgumentException expected) {
384       assertEquals("field A.i has type int, got java.lang.String", expected.getMessage());
385     }
386 
387     // Can't pass an Integer as a String.
388     try {
389       Method m = A.class.getMethod("m", int.class, String.class);
390       m.invoke(new A(), 2, 2);
391       fail();
392     } catch (IllegalArgumentException expected) {
393       assertEquals("method A.m argument 2 has type java.lang.String, got java.lang.Integer",
394           expected.getMessage());
395     }
396 
397     // Can't pass null as an int.
398     try {
399       Method m = A.class.getMethod("m", int.class, String.class);
400       m.invoke(new A(), null, "");
401       fail();
402     } catch (IllegalArgumentException expected) {
403       assertEquals("method A.m argument 1 has type int, got null", expected.getMessage());
404     }
405 
406     try {
407       Method m = String.class.getMethod("charAt", int.class);
408       m.invoke("hello"); // Wrong number of arguments.
409       fail();
410     } catch (IllegalArgumentException iae) {
411       assertEquals("Wrong number of arguments; expected 1, got 0", iae.getMessage());
412     }
413     try {
414       Method m = String.class.getMethod("charAt", int.class);
415       m.invoke("hello", "world"); // Wrong type.
416       fail();
417     } catch (IllegalArgumentException iae) {
418       assertEquals("method java.lang.String.charAt argument 1 has type int, got java.lang.String",
419           iae.getMessage());
420     }
421     try {
422       Method m = String.class.getMethod("charAt", int.class);
423       m.invoke("hello", (Object) null); // Null for a primitive argument.
424       fail();
425     } catch (IllegalArgumentException iae) {
426       assertEquals("method java.lang.String.charAt argument 1 has type int, got null",
427           iae.getMessage());
428     }
429     try {
430       Method m = String.class.getMethod("charAt", int.class);
431       m.invoke(new Integer(5)); // Wrong type for 'this'.
432       fail();
433     } catch (IllegalArgumentException iae) {
434       assertEquals("Expected receiver of type java.lang.String, but got java.lang.Integer",
435           iae.getMessage());
436     }
437     try {
438       Method m = String.class.getMethod("charAt", int.class);
439       m.invoke(null); // Null for 'this'.
440       fail();
441     } catch (NullPointerException npe) {
442       assertEquals("null receiver", npe.getMessage());
443     }
444   }
445 
stringIndex()446   private static void stringIndex() throws Exception {
447     // charAt too small.
448     try {
449       "hello".charAt(-1);
450       fail();
451     } catch (StringIndexOutOfBoundsException ex) {
452       assertEquals("length=5; index=-1", ex.getMessage());
453     }
454 
455     // charAt too big.
456     try {
457       "hello".charAt(7);
458       fail();
459     } catch (StringIndexOutOfBoundsException ex) {
460       assertEquals("length=5; index=7", ex.getMessage());
461     }
462 
463     // substring too big.
464     try {
465       "hello there".substring(9,14);
466       fail();
467     } catch (StringIndexOutOfBoundsException ex) {
468       assertEquals("begin 9, end 14, length 11", ex.getMessage());
469     }
470   }
471 }
472 
473 class A {
474   public String b;
475   public int i;
m(int i, String s)476   public void m(int i, String s) {}
477 }
478