1/* 2 * Copyright (C) 2008 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 libcore.java.util.jar; 18 19import java.io.ByteArrayOutputStream; 20import java.io.File; 21import java.io.FileOutputStream; 22import java.io.IOException; 23import java.io.InputStream; 24import java.util.jar.Attributes; 25import java.util.jar.JarEntry; 26import java.util.jar.JarFile; 27import java.util.jar.JarOutputStream; 28import java.util.jar.Manifest; 29import junit.framework.TestCase; 30import libcore.io.Streams; 31import static tests.support.Support_Exec.execAndGetOutput; 32import tests.support.resource.Support_Resources; 33 34 35public class DalvikExecTest extends TestCase { 36 37 String execDalvik1(String classpath, String mainClass, String arg1) 38 throws IOException, InterruptedException { 39 ProcessBuilder builder = new ProcessBuilder(); 40 41 File dalvikvm = new File("/system/bin/dalvikvm"); 42 if (dalvikvm.exists()) { 43 builder.command().add(dalvikvm.getPath()); 44 } else { 45 builder.command().add("dalvikvm"); // for host mode, assume dalvikvm is on the path 46 } 47 48 builder.command().add("-Duser.language=en"); 49 builder.command().add("-Duser.region=US"); 50 builder.command().add("-Xbootclasspath:" + System.getProperty("java.boot.class.path")); 51 builder.command().add("-classpath"); 52 builder.command().add(classpath); 53 builder.command().add(mainClass); 54 55 if (arg1 != null) { 56 builder.command().add(arg1); 57 } 58 59 // Create a writable dalvik-cache under ANDROID_DATA. 60 // The default dalvik-cache is only writable by the system user (and root). 61 String tmp = System.getProperty("java.io.tmpdir"); 62 builder.environment().put("ANDROID_DATA", tmp); 63 new File(tmp, "dalvik-cache").mkdir(); 64 65 return execAndGetOutput(builder); 66 } 67 68 String execDalvik (String classpath, String mainClass) 69 throws IOException, InterruptedException { 70 return execDalvik1(classpath, mainClass, null); 71 } 72 73 // Execute an existing JAR on dalvikvm using -classpath option.", 74 public void test_execExistingJar () throws IOException, InterruptedException { 75 String res; 76 File jarFile; 77 if (System.getProperty("java.vendor").contains("Android")) { 78 // 79 // Test against Android: 80 // 81 File tempDir = Support_Resources.createTempFolder(); 82 jarFile = Support_Resources.copyFile( 83 tempDir, null, "cts_dalvikExecTest.jar" ); 84 res = execDalvik(jarFile.getAbsolutePath(), "dalvikExecTest.HelloWorld"); 85 assertEquals("Hello Android World!", "Hello Android World!\n", res); 86 87 res = execDalvik(jarFile.getAbsolutePath(), "dalvikExecTest.ResourceDumper"); 88 assertTrue("Android Resource Dumper started", 89 res.contains("Android Resource Dumper started")); 90 assertTrue("This Resource contains some text.", 91 res.contains("This Resource contains some text.")); 92 } else { 93 // 94 // Test against RI: 95 // 96 // Do nothing! 97 } 98 } 99 100 // Create a temp file, fill it with contents according to Dalvik JAR format, and execute it on dalvikvm using -classpath option.", 101 public void test_execCreatedJar () throws IOException, InterruptedException { 102 File jarFile = File.createTempFile("cts_dalvikExecTest_", ".jar"); 103 jarFile.deleteOnExit(); 104 105 // Create a JAR output stream on the temp file: 106 JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(jarFile)); 107 108 // Define the entry for the classes.dex: 109 jarOut.putNextEntry(new JarEntry("classes.dex")); 110 111 // Fill in the classes.dex contents, i.e. the Dalvik executable code: 112 // (See below for the detailed source code contents.) 113 Streams.copy(Support_Resources.getResourceStream("cts_dalvikExecTest_classes.dex"), jarOut); 114 115 // Now add a resource file: 116 // 117 jarOut.putNextEntry(new JarEntry("dalvikExecTest/myResource")); 118 jarOut.write("This Resource contains some text.".getBytes()); 119 120 // Close the stream to the completed JAR file. 121 jarOut.close(); 122 123 // The resulting JAR file contains the classes listed at the end of this text, 124 // like the 'cts_dalvikExecTest.jar' as part of the resources, too. 125 126 String res; 127 128 res = execDalvik(jarFile.getAbsolutePath(), "dalvikExecTest.HelloWorld"); 129 assertEquals("Hello Android World!", "Hello Android World!\n", res); 130 131 res = execDalvik(jarFile.getAbsolutePath(), "dalvikExecTest.ResourceDumper"); 132 assertTrue("Android Resource Dumper started", 133 res.contains("Android Resource Dumper started")); 134 assertTrue("This Resource contains some text.", 135 res.contains("This Resource contains some text.")); 136 } 137 138 139 /** 140 * This test does quite the same as test_execCreatedJar, but includes a manifest. 141 * Note however that the Dalvik JAR format does not require this manifest. 142 * We just test whether the manifest is placed correctly within the JAR by 143 * dumping its contents read as a simple text resource. 144 * No! We can't do that so easily either, as there are other (parent) JARs 145 * with a manifest inside, taken with precedence. 146 * So we will reopen the JAR as a JarFile and check the manifest 147 * with a top level end-to-end approach. 148 */ 149 public void test_execCreatedJarWithManifest () throws IOException, InterruptedException { 150 File jarFile = File.createTempFile("cts_dalvikExecTest_", ".jar"); 151 jarFile.deleteOnExit(); 152 153 // Create the manifest: 154 Manifest manifest = new Manifest(); 155 Attributes attrs = manifest.getMainAttributes(); 156 attrs.put(Attributes.Name.MANIFEST_VERSION, "3.1415962"); 157 attrs.put(Attributes.Name.MAIN_CLASS, "dalvikExecTest.HelloWorld"); 158 attrs.put(Attributes.Name.CLASS_PATH, jarFile.getName()); 159 160 // Create a JAR output stream on the temp file using the manifest: 161 JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(jarFile), manifest); 162 163 // Define the entry for the classes.dex: 164 jarOut.putNextEntry(new JarEntry("classes.dex")); 165 166 // Fill in the classes.dex contents, i.e. the Dalvik executable code: 167 // (See below for the detailed source code contents.) 168 Streams.copy(Support_Resources.getResourceStream("cts_dalvikExecTest_classes.dex"), jarOut); 169 170 // Now add a resource file: 171 // 172 jarOut.putNextEntry(new JarEntry("dalvikExecTest/myResource")); 173 jarOut.write("This Resource contains some text.".getBytes()); 174 175 // Close the stream to the completed JAR file. 176 jarOut.close(); 177 178 // The resulting JAR file contains the classes listed at the end of this text, 179 // like the 'cts_dalvikExecTest.jar' as part of the resources, too. 180 181 String res; 182 183 res = execDalvik(jarFile.getAbsolutePath(), "dalvikExecTest.HelloWorld"); 184 assertEquals("Hello Android World!", "Hello Android World!\n", res); 185 186 res = execDalvik(jarFile.getAbsolutePath(), "dalvikExecTest.ResourceDumper"); 187 assertTrue("Android Resource Dumper started", 188 res.contains("Android Resource Dumper started")); 189 assertTrue("This Resource contains some text.", 190 res.contains("This Resource contains some text.")); 191 192 // And now reread the manifest: 193 // 194 JarFile jarIn = new JarFile(jarFile); 195 manifest = jarIn.getManifest(); 196 attrs = manifest.getMainAttributes(); 197 assertEquals("MANIFEST_VERSION must match!", "3.1415962", 198 attrs.get(Attributes.Name.MANIFEST_VERSION)); 199 assertEquals("MAIN_CLASS must match!", "dalvikExecTest.HelloWorld", 200 attrs.get(Attributes.Name.MAIN_CLASS)); 201 assertEquals("CLASS_PATH must match!", jarFile.getName(), 202 attrs.get(Attributes.Name.CLASS_PATH)); 203 } 204 205 206 /* 207 * The following two classes are added, here, only for completeness. 208 * They form the contents of the dalvikExecTest package contained 209 * in the 'cts_dalvikExecTest_classes.dex' resource file. 210 */ 211 /** 212 * @hide 213 */ 214 public static class HelloWorld { 215 216 public static void main(String[] args) { 217 System.out.println("Hello Android World!"); 218 } 219 220 } 221 222 public static class ResourceDumper { 223 224 static ByteArrayOutputStream outputFrom (InputStream input) throws IOException { 225 ByteArrayOutputStream out = new ByteArrayOutputStream(); 226 byte[] buffer = new byte[512]; 227 int total = 0; 228 int count; 229 count = input.read(buffer); 230 while (count != -1) { 231 out.write(buffer, 0, count); 232 total = total + count; 233 count = input.read(buffer); 234 } 235 return out; 236 } 237 238 public static void main(String[] args) throws IOException { 239 System.out.print("Android Resource Dumper started "); 240 String fileName; 241 if (args.length >= 1) { 242 fileName = args[0]; 243 System.out.format("for argument '%s'.\n", fileName); 244 } else { 245 System.out.print("standard "); 246 fileName = "myResource"; 247 System.out.println("for standard 'myResource'."); 248 } 249 InputStream is = ResourceDumper.class.getResourceAsStream(fileName); 250 if (is != null) { 251 System.out.println("Resource obtained and being dumped:"); 252 System.out.println(outputFrom(is).toString()); 253 } 254 } 255 256 } 257 258} 259