DexMergeTest.java revision 081c7142b29ccd6e1744b26e097b6a4d7c12f2bd
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 com.android.dx.merge;
18
19import dalvik.system.PathClassLoader;
20import java.io.File;
21import java.io.FileInputStream;
22import java.io.FileOutputStream;
23import java.io.IOException;
24import java.io.InputStream;
25import java.io.OutputStream;
26import java.util.Arrays;
27import java.util.jar.JarEntry;
28import java.util.jar.JarOutputStream;
29import junit.framework.TestCase;
30
31/**
32 * Test that DexMerge works by merging dex files, and then loading them into
33 * the current VM.
34 */
35public final class DexMergeTest extends TestCase {
36
37    public void testFillArrayData() throws Exception {
38        ClassLoader loader = mergeAndLoad(
39                "/testdata/Basic.dex",
40                "/testdata/FillArrayData.dex");
41
42        Class<?> basic = loader.loadClass("testdata.Basic");
43        assertEquals(1, basic.getDeclaredMethods().length);
44
45        Class<?> fillArrayData = loader.loadClass("testdata.FillArrayData");
46        assertTrue(Arrays.equals(
47                new byte[] { 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, -112, -23, 121 },
48                (byte[]) fillArrayData.getMethod("newByteArray").invoke(null)));
49        assertTrue(Arrays.equals(
50                new char[] { 0xFFFF, 0x4321, 0xABCD, 0, 'a', 'b', 'c' },
51                (char[]) fillArrayData.getMethod("newCharArray").invoke(null)));
52        assertTrue(Arrays.equals(
53                new long[] { 4660046610375530309L, 7540113804746346429L, -6246583658587674878L },
54                (long[]) fillArrayData.getMethod("newLongArray").invoke(null)));
55    }
56
57    public void testTryCatchFinally() throws Exception {
58        ClassLoader loader = mergeAndLoad(
59                "/testdata/Basic.dex",
60                "/testdata/TryCatchFinally.dex");
61
62        Class<?> basic = loader.loadClass("testdata.Basic");
63        assertEquals(1, basic.getDeclaredMethods().length);
64
65        Class<?> tryCatchFinally = loader.loadClass("testdata.TryCatchFinally");
66        tryCatchFinally.getDeclaredMethod("method").invoke(null);
67    }
68
69    public void testStaticValues() throws Exception {
70        ClassLoader loader = mergeAndLoad(
71                "/testdata/Basic.dex",
72                "/testdata/StaticValues.dex");
73
74        Class<?> basic = loader.loadClass("testdata.Basic");
75        assertEquals(1, basic.getDeclaredMethods().length);
76
77        Class<?> staticValues = loader.loadClass("testdata.StaticValues");
78        assertEquals((byte) 1, staticValues.getField("a").get(null));
79        assertEquals((short) 2, staticValues.getField("b").get(null));
80        assertEquals('C', staticValues.getField("c").get(null));
81        assertEquals(0xabcd1234, staticValues.getField("d").get(null));
82        assertEquals(4660046610375530309L,staticValues.getField("e").get(null));
83        assertEquals(0.5f, staticValues.getField("f").get(null));
84        assertEquals(-0.25, staticValues.getField("g").get(null));
85        assertEquals("this is a String", staticValues.getField("h").get(null));
86        assertEquals(String.class, staticValues.getField("i").get(null));
87        assertEquals("[0, 1]", Arrays.toString((int[]) staticValues.getField("j").get(null)));
88        assertEquals(null, staticValues.getField("k").get(null));
89        assertEquals(true, staticValues.getField("l").get(null));
90        assertEquals(false, staticValues.getField("m").get(null));
91    }
92
93    public ClassLoader mergeAndLoad(String dexAResource, String dexBResource) throws IOException {
94        File dexA = resourceToFile(dexAResource);
95        File dexB = resourceToFile(dexBResource);
96        File mergedDex = File.createTempFile("DexMergeTest", ".classes.dex");
97        new DexMerger(mergedDex, dexA, dexB).merge();
98        File mergedJar = dexToJar(mergedDex);
99        return new PathClassLoader(mergedJar.getPath(), getClass().getClassLoader());
100    }
101
102    private File resourceToFile(String resource) throws IOException {
103        File result = File.createTempFile("DexMergeTest", ".resource");
104        result.deleteOnExit();
105        FileOutputStream out = new FileOutputStream(result);
106        InputStream in = getClass().getResourceAsStream(resource);
107        if (in == null) {
108            throw new IllegalArgumentException("No such resource: " + resource);
109        }
110        copy(in, out);
111        out.close();
112        return result;
113    }
114
115    private File dexToJar(File dex) throws IOException {
116        File result = File.createTempFile("DexMergeTest", ".jar");
117        result.deleteOnExit();
118        JarOutputStream jarOut = new JarOutputStream(new FileOutputStream(result));
119        jarOut.putNextEntry(new JarEntry("classes.dex"));
120        copy(new FileInputStream(dex), jarOut);
121        jarOut.closeEntry();
122        jarOut.close();
123        return result;
124    }
125
126    private void copy(InputStream in, OutputStream out) throws IOException {
127        byte[] buffer = new byte[1024];
128        int count;
129        while ((count = in.read(buffer)) != -1) {
130            out.write(buffer, 0, count);
131        }
132        in.close();
133    }
134}
135