Merge "Add a test for our NPE checks."
diff --git a/test/122-npe/expected.txt b/test/122-npe/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/122-npe/expected.txt
diff --git a/test/122-npe/info.txt b/test/122-npe/info.txt
new file mode 100644
index 0000000..eef46d8
--- /dev/null
+++ b/test/122-npe/info.txt
@@ -0,0 +1 @@
+Test that our NPE checks and stack traces work.
diff --git a/test/122-npe/src/Main.java b/test/122-npe/src/Main.java
new file mode 100644
index 0000000..2fdcb9c
--- /dev/null
+++ b/test/122-npe/src/Main.java
@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Test that null pointer exceptions are thrown by the VM.
+ */
+public class Main {
+ private int f;
+ public static void main(String[] args) {
+ methodOne();
+ }
+
+ static void methodOne() {
+ methodTwo();
+ }
+
+ private int callSpecial() {
+ return f;
+ }
+
+ final int callFinal() {
+ return f;
+ }
+
+ static void methodTwo() {
+ NullPointerException npe = null;
+
+ int thisLine = 41;
+
+ new Object().getClass(); // Ensure compiled.
+ try {
+ ((Object) null).getClass();
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 4);
+
+ new Main().callSpecial(); // Ensure compiled.
+ try {
+ ((Main) null).callSpecial(); // Test invokespecial.
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 8);
+
+ new Main().callFinal(); // Ensure compiled.
+ try {
+ ((Main) null).callFinal(); // Test invokevirtual on final.
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 8);
+
+ try {
+ ((Value) null).objectField.toString();
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((Value) null).intField);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useFloat(((Value) null).floatField);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useLong(((Value) null).longField);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useDouble(((Value) null).doubleField);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((Value) null).objectField = "Fisk";
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((Value) null).intField = 42;
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((Value) null).floatField = 42.0F;
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((Value) null).longField = 42L;
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((Value) null).doubleField = 42.0d;
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((Value) null).byteField);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ if (((Value) null).booleanField) { }
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((Value) null).charField);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((Value) null).shortField);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((Value) null).byteField = 42;
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((Value) null).booleanField = true;
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((Value) null).charField = '\u0042';
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((Value) null).shortField = 42;
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((Object[]) null)[0].toString();
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((int[]) null)[0]);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useFloat(((float[]) null)[0]);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useLong(((long[]) null)[0]);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useDouble(((double[]) null)[0]);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((Object[]) null)[0] = "Fisk";
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((int[]) null)[0] = 42;
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((float[]) null)[0] = 42.0F;
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((long[]) null)[0] = 42L;
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((double[]) null)[0] = 42.0d;
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((byte[]) null)[0]);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ if (((boolean[]) null)[0]) { }
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((char[]) null)[0]);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((short[]) null)[0]);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((byte[]) null)[0] = 42;
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((boolean[]) null)[0] = true;
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((char[]) null)[0] = '\u0042';
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ ((short[]) null)[0] = 42;
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((Object[]) null).length);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((int[]) null).length);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((float[]) null).length);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((long[]) null).length);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((double[]) null).length);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((byte[]) null).length);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((boolean[]) null).length);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((char[]) null).length);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ useInt(((short[]) null).length);
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 7);
+
+ try {
+ Interface i = null;
+ i.methodInterface(); // Test null on invokeinterface.
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 8);
+
+ try {
+ Object o = null;
+ o.toString(); // Test null on invokevirtual.
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 8);
+
+ npe = null;
+ try {
+ String s = null;
+ try {
+ throw new AssertionError();
+ } finally {
+ // Cause an implicit NPE.
+ s.getClass();
+ }
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 13);
+
+ npe = null;
+ try {
+ String s = null;
+ try {
+ throw new AssertionError();
+ } catch (AssertionError ex) {
+ }
+ s.getClass();
+ } catch (NullPointerException e) {
+ npe = e;
+ }
+ check(npe, thisLine += 14);
+ }
+
+ static void check(NullPointerException npe, int firstLine) {
+ final boolean debug = false;
+ if (debug) {
+ System.out.print("Got to line ");
+ System.out.print(firstLine);
+ System.out.println();
+ }
+ StackTraceElement[] trace = npe.getStackTrace();
+ checkElement(trace[0], "Main", "methodTwo", "Main.java", firstLine);
+ checkElement(trace[1], "Main", "methodOne", "Main.java", 27);
+ checkElement(trace[2], "Main", "main", "Main.java", 23);
+ }
+
+ static void checkElement(StackTraceElement element,
+ String declaringClass, String methodName,
+ String fileName, int lineNumber) {
+ assertEquals(declaringClass, element.getClassName());
+ assertEquals(methodName, element.getMethodName());
+ assertEquals(fileName, element.getFileName());
+ assertEquals(lineNumber, element.getLineNumber());
+ }
+
+ static void assertEquals(Object expected, Object actual) {
+ if (!expected.equals(actual)) {
+ String msg = "Expected \"" + expected + "\" but got \"" + actual + "\"";
+ throw new AssertionError(msg);
+ }
+ }
+
+ static void assertEquals(int expected, int actual) {
+ if (expected != actual) {
+ throw new AssertionError("Expected " + expected + " got " + actual);
+ }
+ }
+
+ interface Interface {
+ void methodInterface();
+ }
+
+ static void useInt(int i) {
+ }
+
+ static void useFloat(float f) {
+ }
+
+ static void useDouble(double d) {
+ }
+
+ static void useLong(long l) {
+ }
+
+ static class Value {
+ Object objectField;
+ int intField;
+ float floatField; long longField;
+ double doubleField;
+ byte byteField;
+ boolean booleanField;
+ char charField;
+ short shortField;
+ }
+}