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 testCases.add(new TestCase("PackedSwitch key INT_MAX", "PackedSwitch", 55 "packedSwitch_INT_MAX", new Object[]{123}, null, 123)); 56 testCases.add(new TestCase("PackedSwitch key overflow", "b_24399945", 57 "packedSwitch_overflow", new Object[]{123}, new VerifyError(), null)); 58 59 testCases.add(new TestCase("b/17790197", "B17790197", "getInt", null, null, 100)); 60 testCases.add(new TestCase("FloatBadArgReg", "FloatBadArgReg", "getInt", 61 new Object[]{100}, null, 100)); 62 testCases.add(new TestCase("negLong", "negLong", "negLong", null, null, 122142L)); 63 testCases.add(new TestCase("sameFieldNames", "sameFieldNames", "getInt", null, null, 7)); 64 testCases.add(new TestCase("b/18380491", "B18380491ConcreteClass", "foo", 65 new Object[]{42}, null, 42)); 66 testCases.add(new TestCase("invoke-super abstract", "B18380491ConcreteClass", "foo", 67 new Object[]{0}, new AbstractMethodError(), null)); 68 testCases.add(new TestCase("BadCaseInOpRegRegReg", "BadCaseInOpRegRegReg", "getInt", null, 69 null, 2)); 70 testCases.add(new TestCase("CmpLong", "CmpLong", "run", null, null, 0)); 71 testCases.add(new TestCase("FloatIntConstPassing", "FloatIntConstPassing", "run", null, 72 null, 2)); 73 testCases.add(new TestCase("b/18718277", "B18718277", "getInt", null, null, 0)); 74 testCases.add(new TestCase("b/18800943 (1)", "B18800943_1", "n_a", null, new VerifyError(), 75 0)); 76 testCases.add(new TestCase("b/18800943 (2)", "B18800943_2", "n_a", null, new VerifyError(), 77 0)); 78 testCases.add(new TestCase("MoveExc", "MoveExc", "run", null, new ArithmeticException(), 79 null)); 80 testCases.add(new TestCase("MoveExceptionOnEntry", "MoveExceptionOnEntry", 81 "moveExceptionOnEntry", new Object[]{0}, new VerifyError(), null)); 82 testCases.add(new TestCase("EmptySparseSwitch", "EmptySparseSwitch", "run", null, null, 83 null)); 84 testCases.add(new TestCase("b/20224106", "B20224106", "run", null, new VerifyError(), 85 0)); 86 testCases.add(new TestCase("b/17410612", "B17410612", "run", null, new VerifyError(), 87 0)); 88 testCases.add(new TestCase("b/21863767", "B21863767", "run", null, null, 89 null)); 90 testCases.add(new TestCase("b/21873167", "B21873167", "test", null, null, null)); 91 testCases.add(new TestCase("b/21614284", "B21614284", "test", new Object[] { null }, 92 new NullPointerException(), null)); 93 testCases.add(new TestCase("b/21902684", "B21902684", "test", null, null, null)); 94 testCases.add(new TestCase("b/22045582", "B22045582", "run", null, new VerifyError(), 95 0)); 96 testCases.add(new TestCase("b/22045582 (int)", "B22045582Int", "run", null, 97 new VerifyError(), 0)); 98 testCases.add(new TestCase("b/22045582 (wide)", "B22045582Wide", "run", null, 99 new VerifyError(), 0)); 100 testCases.add(new TestCase("b/21886894", "B21886894", "test", null, new VerifyError(), 101 null)); 102 testCases.add(new TestCase("b/22080519", "B22080519", "run", null, 103 new NullPointerException(), null)); 104 testCases.add(new TestCase("b/21645819", "B21645819", "run", new Object[] { null }, 105 null, null)); 106 testCases.add(new TestCase("b/22244733", "B22244733", "run", new Object[] { "abc" }, 107 null, "abc")); 108 testCases.add(new TestCase("b/22331663", "B22331663", "run", new Object[] { false }, 109 null, null)); 110 testCases.add(new TestCase("b/22331663 (pass)", "B22331663Pass", "run", 111 new Object[] { false }, null, null)); 112 testCases.add(new TestCase("b/22331663 (fail)", "B22331663Fail", "run", 113 new Object[] { false }, new VerifyError(), null)); 114 testCases.add(new TestCase("b/22411633 (1)", "B22411633_1", "run", new Object[] { false }, 115 null, null)); 116 testCases.add(new TestCase("b/22411633 (2)", "B22411633_2", "run", new Object[] { false }, 117 new VerifyError(), null)); 118 testCases.add(new TestCase("b/22411633 (3)", "B22411633_3", "run", new Object[] { false }, 119 null, null)); 120 testCases.add(new TestCase("b/22411633 (4)", "B22411633_4", "run", new Object[] { false }, 121 new VerifyError(), null)); 122 testCases.add(new TestCase("b/22411633 (5)", "B22411633_5", "run", new Object[] { false }, 123 null, null)); 124 testCases.add(new TestCase("b/22777307", "B22777307", "run", null, new InstantiationError(), 125 null)); 126 testCases.add(new TestCase("b/22881413", "B22881413", "run", null, null, null)); 127 testCases.add(new TestCase("b/20843113", "B20843113", "run", null, null, null)); 128 testCases.add(new TestCase("b/23201502 (float)", "B23201502", "runFloat", null, 129 new NullPointerException(), null)); 130 testCases.add(new TestCase("b/23201502 (double)", "B23201502", "runDouble", null, 131 new NullPointerException(), null)); 132 testCases.add(new TestCase("b/23300986", "B23300986", "runAliasAfterEnter", 133 new Object[] { new Object() }, null, null)); 134 testCases.add(new TestCase("b/23300986 (2)", "B23300986", "runAliasBeforeEnter", 135 new Object[] { new Object() }, null, null)); 136 testCases.add(new TestCase("b/23502994 (if-eqz)", "B23502994", "runIF_EQZ", 137 new Object[] { new Object() }, null, null)); 138 testCases.add(new TestCase("b/23502994 (check-cast)", "B23502994", "runCHECKCAST", 139 new Object[] { "abc" }, null, null)); 140 testCases.add(new TestCase("b/25494456", "B25494456", "run", null, new VerifyError(), 141 null)); 142 testCases.add(new TestCase("b/21869691", "B21869691A", "run", null, 143 new IncompatibleClassChangeError(), null)); 144 testCases.add(new TestCase("b/26143249", "B26143249", "run", null, 145 new AbstractMethodError(), null)); 146 testCases.add(new TestCase("b/26579108", "B26579108", "run", null, new VerifyError(), 147 null)); 148 testCases.add(new TestCase("b/26594149 (1)", "B26594149_1", "run", null, new VerifyError(), 149 null)); 150 testCases.add(new TestCase("b/26594149 (2)", "B26594149_2", "run", null, new VerifyError(), 151 null)); 152 testCases.add(new TestCase("b/26594149 (3)", "B26594149_3", "run", null, new VerifyError(), 153 null)); 154 testCases.add(new TestCase("b/26594149 (4)", "B26594149_4", "run", null, new VerifyError(), 155 null)); 156 testCases.add(new TestCase("b/26594149 (5)", "B26594149_5", "run", null, null, null)); 157 testCases.add(new TestCase("b/26594149 (6)", "B26594149_6", "run", null, new VerifyError(), 158 null)); 159 testCases.add(new TestCase("b/26594149 (7)", "B26594149_7", "run", null, new VerifyError(), 160 null)); 161 testCases.add(new TestCase("b/26594149 (8)", "B26594149_8", "run", null, new VerifyError(), 162 null)); 163 testCases.add(new TestCase("b/27148248", "B27148248", "run", null, new VerifyError(), 164 null)); 165 testCases.add(new TestCase("b/26965384", "B26965384", "run", null, new VerifyError(), 166 null)); 167 testCases.add(new TestCase("b/27799205 (1)", "B27799205Helper", "run1", null, null, null)); 168 testCases.add(new TestCase("b/27799205 (2)", "B27799205Helper", "run2", null, 169 new VerifyError(), null)); 170 testCases.add(new TestCase("b/27799205 (3)", "B27799205Helper", "run3", null, 171 new VerifyError(), null)); 172 testCases.add(new TestCase("b/27799205 (4)", "B27799205Helper", "run4", null, 173 new VerifyError(), null)); 174 testCases.add(new TestCase("b/27799205 (5)", "B27799205Helper", "run5", null, 175 new VerifyError(), null)); 176 testCases.add(new TestCase("b/27799205 (6)", "B27799205Helper", "run6", null, null, null)); 177 testCases.add(new TestCase("b/28187158", "B28187158", "run", new Object[] { null} , 178 new VerifyError(), null)); 179 } 180 runTests()181 public void runTests() { 182 for (TestCase tc : testCases) { 183 System.out.println(tc.testName); 184 try { 185 runTest(tc); 186 } catch (Exception exc) { 187 exc.printStackTrace(System.out); 188 } 189 } 190 } 191 runTest(TestCase tc)192 private void runTest(TestCase tc) throws Exception { 193 Exception errorReturn = null; 194 try { 195 Class<?> c = Class.forName(tc.testClass); 196 197 Method[] methods = c.getDeclaredMethods(); 198 199 // For simplicity we assume that test methods are not overloaded. So searching by name 200 // will give us the method we need to run. 201 Method method = null; 202 for (Method m : methods) { 203 if (m.getName().equals(tc.testMethodName)) { 204 method = m; 205 break; 206 } 207 } 208 209 if (method == null) { 210 errorReturn = new IllegalArgumentException("Could not find test method " + 211 tc.testMethodName + " in class " + 212 tc.testClass + " for test " + 213 tc.testName); 214 } else { 215 Object retValue; 216 if (Modifier.isStatic(method.getModifiers())) { 217 retValue = method.invoke(null, tc.values); 218 } else { 219 retValue = method.invoke(method.getDeclaringClass().newInstance(), tc.values); 220 } 221 if (tc.expectedException != null) { 222 errorReturn = new IllegalStateException("Expected an exception in test " + 223 tc.testName); 224 } else if (tc.expectedReturn == null && retValue != null) { 225 errorReturn = new IllegalStateException("Expected a null result in test " + 226 tc.testName); 227 } else if (tc.expectedReturn != null && 228 (retValue == null || !tc.expectedReturn.equals(retValue))) { 229 errorReturn = new IllegalStateException("Expected return " + 230 tc.expectedReturn + 231 ", but got " + retValue); 232 } else { 233 // Expected result, do nothing. 234 } 235 } 236 } catch (Throwable exc) { 237 if (tc.expectedException == null) { 238 errorReturn = new IllegalStateException("Did not expect exception", exc); 239 } else if (exc instanceof InvocationTargetException && exc.getCause() != null && 240 exc.getCause().getClass().equals(tc.expectedException.getClass())) { 241 // Expected exception is wrapped in InvocationTargetException. 242 } else if (!tc.expectedException.getClass().equals(exc.getClass())) { 243 errorReturn = new IllegalStateException("Expected " + 244 tc.expectedException.getClass().getName() + 245 ", but got " + exc.getClass(), exc); 246 } else { 247 // Expected exception, do nothing. 248 } 249 } finally { 250 if (errorReturn != null) { 251 throw errorReturn; 252 } 253 } 254 } 255 main(String[] args)256 public static void main(String[] args) throws Exception { 257 Main main = new Main(); 258 259 main.runTests(); 260 261 System.out.println("Done!"); 262 } 263 } 264