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 17 import java.lang.reflect.InvocationTargetException; 18 import java.lang.reflect.Method; 19 import java.lang.reflect.Modifier; 20 import java.util.LinkedList; 21 import java.util.List; 22 23 /** 24 * Smali excercise. 25 */ 26 public class Main { 27 28 private static class TestCase { TestCase(String testName, String testClass, String testMethodName, Object[] values, Throwable expectedException, Object expectedReturn)29 public TestCase(String testName, String testClass, String testMethodName, Object[] values, 30 Throwable expectedException, Object expectedReturn) { 31 this.testName = testName; 32 this.testClass = testClass; 33 this.testMethodName = testMethodName; 34 this.values = values; 35 this.expectedException = expectedException; 36 this.expectedReturn = expectedReturn; 37 } 38 39 String testName; 40 String testClass; 41 String testMethodName; 42 Object[] values; 43 Throwable expectedException; 44 Object expectedReturn; 45 } 46 47 private List<TestCase> testCases; 48 Main()49 public Main() { 50 // Create the test cases. 51 testCases = new LinkedList<TestCase>(); 52 testCases.add(new TestCase("PackedSwitch", "PackedSwitch", "packedSwitch", 53 new Object[]{123}, null, 123)); 54 55 testCases.add(new TestCase("b/17790197", "B17790197", "getInt", null, null, 100)); 56 testCases.add(new TestCase("b/17978759", "B17978759", "test", null, new VerifyError(), 57 null)); 58 testCases.add(new TestCase("FloatBadArgReg", "FloatBadArgReg", "getInt", 59 new Object[]{100}, null, 100)); 60 testCases.add(new TestCase("negLong", "negLong", "negLong", null, null, 122142L)); 61 testCases.add(new TestCase("sameFieldNames", "sameFieldNames", "getInt", null, null, 7)); 62 testCases.add(new TestCase("b/18380491", "B18380491ConcreteClass", "foo", 63 new Object[]{42}, null, 42)); 64 testCases.add(new TestCase("invoke-super abstract", "B18380491ConcreteClass", "foo", 65 new Object[]{0}, new AbstractMethodError(), null)); 66 testCases.add(new TestCase("BadCaseInOpRegRegReg", "BadCaseInOpRegRegReg", "getInt", null, 67 null, 2)); 68 testCases.add(new TestCase("CmpLong", "CmpLong", "run", null, null, 0)); 69 testCases.add(new TestCase("FloatIntConstPassing", "FloatIntConstPassing", "run", null, 70 null, 2)); 71 testCases.add(new TestCase("b/18718277", "B18718277", "getInt", null, null, 0)); 72 testCases.add(new TestCase("b/18800943 (1)", "B18800943_1", "n_a", null, new VerifyError(), 73 0)); 74 testCases.add(new TestCase("b/18800943 (2)", "B18800943_2", "n_a", null, new VerifyError(), 75 0)); 76 testCases.add(new TestCase("MoveExc", "MoveExc", "run", null, new ArithmeticException(), 77 null)); 78 testCases.add(new TestCase("MoveExceptionOnEntry", "MoveExceptionOnEntry", 79 "moveExceptionOnEntry", new Object[]{0}, new VerifyError(), null)); 80 testCases.add(new TestCase("EmptySparseSwitch", "EmptySparseSwitch", "run", null, null, 81 null)); 82 testCases.add(new TestCase("b/20224106", "B20224106", "run", null, new VerifyError(), 83 0)); 84 testCases.add(new TestCase("b/21873167", "B21873167", "test", null, null, null)); 85 testCases.add(new TestCase("b/21614284", "B21614284", "test", new Object[] { null }, 86 new NullPointerException(), null)); 87 testCases.add(new TestCase("b/21902684", "B21902684", "test", null, null, null)); 88 testCases.add(new TestCase("b/21863767", "B21863767", "run", null, null, 89 null)); 90 testCases.add(new TestCase("b/21886894", "B21886894", "test", null, new VerifyError(), 91 null)); 92 testCases.add(new TestCase("b/22080519", "B22080519", "run", null, 93 new NullPointerException(), null)); 94 testCases.add(new TestCase("b/21645819", "B21645819", "run", new Object[] { null }, 95 null, null)); 96 testCases.add(new TestCase("b/22244733", "B22244733", "run", new Object[] { "abc" }, 97 null, "abc")); 98 testCases.add(new TestCase("b/22331663", "B22331663", "run", new Object[] { false }, 99 null, null)); 100 testCases.add(new TestCase("b/22331663 (pass)", "B22331663Pass", "run", 101 new Object[] { false }, null, null)); 102 testCases.add(new TestCase("b/22331663 (fail)", "B22331663Fail", "run", 103 new Object[] { false }, new VerifyError(), null)); 104 testCases.add(new TestCase("b/22881413", "B22881413", "run", null, null, null)); 105 testCases.add(new TestCase("b/20843113", "B20843113", "run", null, null, null)); 106 testCases.add(new TestCase("b/23201502 (float)", "B23201502", "runFloat", null, 107 new NullPointerException(), null)); 108 testCases.add(new TestCase("b/23201502 (double)", "B23201502", "runDouble", null, 109 new NullPointerException(), null)); 110 } 111 runTests()112 public void runTests() { 113 for (TestCase tc : testCases) { 114 System.out.println(tc.testName); 115 try { 116 runTest(tc); 117 } catch (Exception exc) { 118 exc.printStackTrace(System.out); 119 } 120 } 121 } 122 runTest(TestCase tc)123 private void runTest(TestCase tc) throws Exception { 124 Exception errorReturn = null; 125 try { 126 Class<?> c = Class.forName(tc.testClass); 127 128 Method[] methods = c.getDeclaredMethods(); 129 130 // For simplicity we assume that test methods are not overloaded. So searching by name 131 // will give us the method we need to run. 132 Method method = null; 133 for (Method m : methods) { 134 if (m.getName().equals(tc.testMethodName)) { 135 method = m; 136 break; 137 } 138 } 139 140 if (method == null) { 141 errorReturn = new IllegalArgumentException("Could not find test method " + 142 tc.testMethodName + " in class " + 143 tc.testClass + " for test " + 144 tc.testName); 145 } else { 146 Object retValue; 147 if (Modifier.isStatic(method.getModifiers())) { 148 retValue = method.invoke(null, tc.values); 149 } else { 150 retValue = method.invoke(method.getDeclaringClass().newInstance(), tc.values); 151 } 152 if (tc.expectedException != null) { 153 errorReturn = new IllegalStateException("Expected an exception in test " + 154 tc.testName); 155 } 156 if (tc.expectedReturn == null && retValue != null) { 157 errorReturn = new IllegalStateException("Expected a null result in test " + 158 tc.testName); 159 } else if (tc.expectedReturn != null && 160 (retValue == null || !tc.expectedReturn.equals(retValue))) { 161 errorReturn = new IllegalStateException("Expected return " + 162 tc.expectedReturn + 163 ", but got " + retValue); 164 } else { 165 // Expected result, do nothing. 166 } 167 } 168 } catch (Throwable exc) { 169 if (tc.expectedException == null) { 170 errorReturn = new IllegalStateException("Did not expect exception", exc); 171 } else if (exc instanceof InvocationTargetException && exc.getCause() != null && 172 exc.getCause().getClass().equals(tc.expectedException.getClass())) { 173 // Expected exception is wrapped in InvocationTargetException. 174 } else if (!tc.expectedException.getClass().equals(exc.getClass())) { 175 errorReturn = new IllegalStateException("Expected " + 176 tc.expectedException.getClass().getName() + 177 ", but got " + exc.getClass(), exc); 178 } else { 179 // Expected exception, do nothing. 180 } 181 } finally { 182 if (errorReturn != null) { 183 throw errorReturn; 184 } 185 } 186 } 187 main(String[] args)188 public static void main(String[] args) throws Exception { 189 Main main = new Main(); 190 191 main.runTests(); 192 193 System.out.println("Done!"); 194 } 195 } 196