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 { 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 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 testCases.add(new TestCase("b/29778499 (1)", "B29778499_1", "run", null, 180 new IncompatibleClassChangeError(), null)); 181 testCases.add(new TestCase("b/29778499 (2)", "B29778499_2", "run", null, 182 new IncompatibleClassChangeError(), null)); 183 } 184 185 public void runTests() { 186 for (TestCase tc : testCases) { 187 System.out.println(tc.testName); 188 try { 189 runTest(tc); 190 } catch (Exception exc) { 191 exc.printStackTrace(System.out); 192 } 193 } 194 } 195 196 private void runTest(TestCase tc) throws Exception { 197 Exception errorReturn = null; 198 try { 199 Class<?> c = Class.forName(tc.testClass); 200 201 Method[] methods = c.getDeclaredMethods(); 202 203 // For simplicity we assume that test methods are not overloaded. So searching by name 204 // will give us the method we need to run. 205 Method method = null; 206 for (Method m : methods) { 207 if (m.getName().equals(tc.testMethodName)) { 208 method = m; 209 break; 210 } 211 } 212 213 if (method == null) { 214 errorReturn = new IllegalArgumentException("Could not find test method " + 215 tc.testMethodName + " in class " + 216 tc.testClass + " for test " + 217 tc.testName); 218 } else { 219 Object retValue; 220 if (Modifier.isStatic(method.getModifiers())) { 221 retValue = method.invoke(null, tc.values); 222 } else { 223 retValue = method.invoke(method.getDeclaringClass().newInstance(), tc.values); 224 } 225 if (tc.expectedException != null) { 226 errorReturn = new IllegalStateException("Expected an exception in test " + 227 tc.testName); 228 } else if (tc.expectedReturn == null && retValue != null) { 229 errorReturn = new IllegalStateException("Expected a null result in test " + 230 tc.testName); 231 } else if (tc.expectedReturn != null && 232 (retValue == null || !tc.expectedReturn.equals(retValue))) { 233 errorReturn = new IllegalStateException("Expected return " + 234 tc.expectedReturn + 235 ", but got " + retValue); 236 } else { 237 // Expected result, do nothing. 238 } 239 } 240 } catch (Throwable exc) { 241 if (tc.expectedException == null) { 242 errorReturn = new IllegalStateException("Did not expect exception", exc); 243 } else if (exc instanceof InvocationTargetException && exc.getCause() != null && 244 exc.getCause().getClass().equals(tc.expectedException.getClass())) { 245 // Expected exception is wrapped in InvocationTargetException. 246 } else if (!tc.expectedException.getClass().equals(exc.getClass())) { 247 errorReturn = new IllegalStateException("Expected " + 248 tc.expectedException.getClass().getName() + 249 ", but got " + exc.getClass(), exc); 250 } else { 251 // Expected exception, do nothing. 252 } 253 } finally { 254 if (errorReturn != null) { 255 throw errorReturn; 256 } 257 } 258 } 259 260 public static void main(String[] args) throws Exception { 261 Main main = new Main(); 262 263 main.runTests(); 264 265 System.out.println("Done!"); 266 } 267 } 268