DexClassLoaderTest.java revision 8c47f104820836f6bdacce83e1be6cc71c1cace0
1/* 2 * Copyright (C) 2011 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 17package dalvik.system; 18 19import java.lang.reflect.InvocationTargetException; 20import java.lang.reflect.Method; 21import java.io.File; 22import java.io.FileOutputStream; 23import java.io.IOException; 24import java.io.InputStream; 25import java.io.UnsupportedEncodingException; 26import libcore.base.Streams; 27import junit.framework.TestCase; 28 29/** 30 * Tests for the class {@link DexClassLoader}. 31 */ 32public class DexClassLoaderTest extends TestCase { 33 private static final String PACKAGE_PATH = "dalvik/system/"; 34 private static final String JAR_NAME = "loading-test.jar"; 35 private static final String DEX_NAME = "loading-test.dex"; 36 private static final File TMP_DIR = 37 new File(System.getProperty("java.io.tmpdir"), "loading-test"); 38 private static final File TMP_JAR = new File(TMP_DIR, JAR_NAME); 39 private static final File TMP_DEX = new File(TMP_DIR, DEX_NAME); 40 41 protected void setUp() throws IOException { 42 TMP_DIR.mkdirs(); 43 44 ClassLoader cl = DexClassLoaderTest.class.getClassLoader(); 45 46 InputStream in = cl.getResourceAsStream(PACKAGE_PATH + JAR_NAME); 47 FileOutputStream out = new FileOutputStream(TMP_JAR); 48 Streams.copy(in, out); 49 in.close(); 50 out.close(); 51 52 in = cl.getResourceAsStream(PACKAGE_PATH + DEX_NAME); 53 out = new FileOutputStream(TMP_DEX); 54 Streams.copy(in, out); 55 in.close(); 56 out.close(); 57 } 58 59 /** 60 * Helper to construct an instance to test. 61 * 62 * @param useDex whether to use the raw dex file ({@code true}) or 63 * a dex-in-jar file ({@code false}) 64 */ 65 private static DexClassLoader createInstance(boolean useDex) { 66 File file = useDex ? TMP_DEX : TMP_JAR; 67 68 return new DexClassLoader(file.getAbsolutePath(), 69 TMP_DIR.getAbsolutePath(), 70 null, 71 ClassLoader.getSystemClassLoader()); 72 } 73 74 /** 75 * Helper to construct an instance to test, using the jar file as 76 * the source, and call a named no-argument static method on a 77 * named class. 78 * 79 * @param useDex whether to use the raw dex file ({@code true}) or 80 * a dex-in-jar file ({@code false}) 81 */ 82 public static Object createInstanceAndCallStaticMethod(boolean useDex, 83 String className, String methodName) 84 throws ClassNotFoundException, NoSuchMethodException, 85 IllegalAccessException, InvocationTargetException { 86 DexClassLoader dcl = createInstance(useDex); 87 Class c = dcl.loadClass(className); 88 Method m = c.getMethod(methodName, (Class[]) null); 89 return m.invoke(null, (Object[]) null); 90 } 91 92 /* 93 * Tests that are parametric with respect to whether to use a jar 94 * file or a dex file as the source of the code 95 */ 96 97 /** 98 * Just a trivial test of construction. This one merely makes 99 * sure that a valid construction doesn't fail; it doesn't try 100 * to verify anything about the constructed instance. (Other 101 * tests will do that.) 102 */ 103 public static void test_init(boolean useDex) { 104 createInstance(useDex); 105 } 106 107 /** 108 * Check that a class in the jar file may be used successfully. In this 109 * case, a trivial static method is called. 110 */ 111 public static void test_simpleUse(boolean useDex) throws Exception { 112 String result = (String) 113 createInstanceAndCallStaticMethod(useDex, "test.Test1", "test"); 114 115 assertSame("blort", result); 116 } 117 118 /** 119 * Check that a resource in the jar file is retrievable and contains 120 * the expected contents. 121 */ 122 public static void test_getResourceAsStream(boolean useDex) 123 throws Exception { 124 DexClassLoader dcl = createInstance(useDex); 125 InputStream in = dcl.getResourceAsStream("test/Resource1.txt"); 126 byte[] contents = Streams.readFully(in); 127 String s = new String(contents, "UTF-8"); 128 129 assertEquals("Muffins are tasty!\n", s); 130 } 131 132 /* 133 * All the following tests are just pass-throughs to test code 134 * that lives inside the loading-test dex/jar file. 135 */ 136 137 public static void test_callStaticMethod(boolean useDex) 138 throws Exception { 139 createInstanceAndCallStaticMethod( 140 useDex, "test.Test2", "test_callStaticMethod"); 141 } 142 143 public static void test_getStaticVariable(boolean useDex) 144 throws Exception { 145 createInstanceAndCallStaticMethod( 146 useDex, "test.Test2", "test_getStaticVariable"); 147 } 148 149 public static void test_callInstanceMethod(boolean useDex) 150 throws Exception { 151 createInstanceAndCallStaticMethod( 152 useDex, "test.Test2", "test_callInstanceMethod"); 153 } 154 155 public static void test_getInstanceVariable(boolean useDex) 156 throws Exception { 157 createInstanceAndCallStaticMethod( 158 useDex, "test.Test2", "test_getInstanceVariable"); 159 } 160 161 /* 162 * The rest of the file consists of the actual test methods, which 163 * are all mostly just calls to the parametrically-defined tests 164 * above. 165 */ 166 167 public void test_jar_init() throws Exception { 168 test_init(false); 169 } 170 171 public void test_jar_simpleUse() throws Exception { 172 test_simpleUse(false); 173 } 174 175 public void test_jar_getResourceAsStream() throws Exception { 176 test_getResourceAsStream(false); 177 } 178 179 public void test_jar_callStaticMethod() throws Exception { 180 test_callStaticMethod(false); 181 } 182 183 public void test_jar_getStaticVariable() throws Exception { 184 test_getStaticVariable(false); 185 } 186 187 public void test_jar_callInstanceMethod() throws Exception { 188 test_callInstanceMethod(false); 189 } 190 191 public void test_jar_getInstanceVariable() throws Exception { 192 test_getInstanceVariable(false); 193 } 194 195 public void test_dex_init() throws Exception { 196 test_init(true); 197 } 198 199 public void test_dex_simpleUse() throws Exception { 200 test_simpleUse(true); 201 } 202 203 /* 204 * Note: No getResourceAsStream() test, since the dex file doesn't 205 * have any resources. 206 */ 207 // public void test_dex_getResourceAsStream() 208 209 public void test_dex_callStaticMethod() throws Exception { 210 test_callStaticMethod(true); 211 } 212 213 public void test_dex_getStaticVariable() throws Exception { 214 test_getStaticVariable(true); 215 } 216 217 public void test_dex_callInstanceMethod() throws Exception { 218 test_callInstanceMethod(true); 219 } 220 221 public void test_dex_getInstanceVariable() throws Exception { 222 test_getInstanceVariable(true); 223 } 224} 225