Avoid abort in malformed dex code.

Don't allow a perceived double monitor-enter on a register
to abort libartd.
Allow expected verifier errors in the smali tests.
Tidy includes in the method verifier.
Bug: 17978759

Change-Id: Ic44924c788cd2334f91a047fb41b459b89a1843b
diff --git a/test/800-smali/src/Main.java b/test/800-smali/src/Main.java
index 87549d9..014edc0 100644
--- a/test/800-smali/src/Main.java
+++ b/test/800-smali/src/Main.java
@@ -15,6 +15,7 @@
  */
 
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -49,6 +50,7 @@
         testCases = new LinkedList<TestCase>();
 
         testCases.add(new TestCase("b/17790197", "B17790197", "getInt", null, null, 100));
+        testCases.add(new TestCase("b/17978759", "B17978759", "test", null, new VerifyError(), null));
         testCases.add(new TestCase("FloatBadArgReg", "FloatBadArgReg", "getInt",
             new Object[]{100}, null, 100));
         testCases.add(new TestCase("negLong", "negLong", "negLong", null, null, 122142L));
@@ -66,47 +68,59 @@
     }
 
     private void runTest(TestCase tc) throws Exception {
-        Class<?> c = Class.forName(tc.testClass);
-
-        Method[] methods = c.getDeclaredMethods();
-
-        // For simplicity we assume that test methods are not overloaded. So searching by name
-        // will give us the method we need to run.
-        Method method = null;
-        for (Method m : methods) {
-            if (m.getName().equals(tc.testMethodName)) {
-                method = m;
-                break;
-            }
-        }
-
-        if (method == null) {
-            throw new IllegalArgumentException("Could not find test method " + tc.testMethodName +
-                    " in class " + tc.testClass + " for test " + tc.testName);
-        }
-
         Exception errorReturn = null;
         try {
-            Object retValue = method.invoke(null, tc.values);
-            if (tc.expectedException != null) {
-                errorReturn = new IllegalStateException("Expected an exception in test " +
-                                                        tc.testName);
+            Class<?> c = Class.forName(tc.testClass);
+
+            Method[] methods = c.getDeclaredMethods();
+
+            // For simplicity we assume that test methods are not overloaded. So searching by name
+            // will give us the method we need to run.
+            Method method = null;
+            for (Method m : methods) {
+                if (m.getName().equals(tc.testMethodName)) {
+                    method = m;
+                    break;
+                }
             }
-            if (tc.expectedReturn == null && retValue != null) {
-                errorReturn = new IllegalStateException("Expected a null result in test " +
-                                                        tc.testName);
-            } else if (tc.expectedReturn != null &&
-                       (retValue == null || !tc.expectedReturn.equals(retValue))) {
-                errorReturn = new IllegalStateException("Expected return " + tc.expectedReturn +
-                                                        ", but got " + retValue);
+
+            if (method == null) {
+                errorReturn = new IllegalArgumentException("Could not find test method " +
+                                                           tc.testMethodName + " in class " +
+                                                           tc.testClass + " for test " +
+                                                           tc.testName);
+            } else {
+                Object retValue;
+                if (Modifier.isStatic(method.getModifiers())) {
+                    retValue = method.invoke(null, tc.values);
+                } else {
+                    retValue = method.invoke(method.getDeclaringClass().newInstance(), tc.values);
+                }
+                if (tc.expectedException != null) {
+                    errorReturn = new IllegalStateException("Expected an exception in test " +
+                                                            tc.testName);
+                }
+                if (tc.expectedReturn == null && retValue != null) {
+                    errorReturn = new IllegalStateException("Expected a null result in test " +
+                                                            tc.testName);
+                } else if (tc.expectedReturn != null &&
+                           (retValue == null || !tc.expectedReturn.equals(retValue))) {
+                    errorReturn = new IllegalStateException("Expected return " +
+                                                            tc.expectedReturn +
+                                                            ", but got " + retValue);
+                } else {
+                    // Expected result, do nothing.
+                }
             }
-        } catch (Exception exc) {
+        } catch (Throwable exc) {
             if (tc.expectedException == null) {
                 errorReturn = new IllegalStateException("Did not expect exception", exc);
             } else if (!tc.expectedException.getClass().equals(exc.getClass())) {
                 errorReturn = new IllegalStateException("Expected " +
-                                                tc.expectedException.getClass().getName() +
-                                                ", but got " + exc.getClass(), exc);
+                                                        tc.expectedException.getClass().getName() +
+                                                        ", but got " + exc.getClass(), exc);
+            } else {
+              // Expected exception, do nothing.
             }
         } finally {
             if (errorReturn != null) {