ClassLoaderTest.java revision 89c1feb0a69a7707b271086e749975b3f7acacf7
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package org.apache.harmony.luni.tests.java.lang;
19
20import dalvik.annotation.TestInfo;
21import dalvik.annotation.TestLevel;
22import dalvik.annotation.TestTarget;
23import dalvik.annotation.TestTargetClass;
24
25import junit.framework.TestCase;
26
27import java.io.File;
28import java.io.InputStream;
29import java.security.CodeSource;
30import java.security.Permission;
31import java.security.PermissionCollection;
32import java.security.Policy;
33import java.security.ProtectionDomain;
34import java.security.SecurityPermission;
35
36@TestTargetClass(ClassLoader.class)
37public class ClassLoaderTest extends TestCase {
38
39    public static volatile int flag;
40
41    /**
42     * Tests that Classloader.defineClass() assigns appropriate
43     * default domains to the defined classes.
44     */
45    @TestInfo(
46      level = TestLevel.PARTIAL,
47      purpose = "Verifies only positive functionality.",
48      targets = {
49        @TestTarget(
50          methodName = "defineClass",
51          methodArgs = {java.lang.String.class, byte[].class, int.class, int.class}
52        )
53    })
54    public void _test_defineClass_defaultDomain() throws Exception {
55        // Regression for HARMONY-765
56        DynamicPolicy plc = new DynamicPolicy();
57        Policy back = Policy.getPolicy();
58        try {
59            Policy.setPolicy(plc);
60
61            Class<?> a = new Ldr().define();
62
63            Permission p = new SecurityPermission("abc");
64            assertFalse("impossible! misconfiguration?", a.getProtectionDomain().implies(p));
65
66            plc.pc = p.newPermissionCollection();
67            plc.pc.add(p);
68            assertTrue("default domain is not dynamic", a.getProtectionDomain().implies(p));
69        } finally {
70            Policy.setPolicy(back);
71        }
72    }
73
74    static class SyncTestClassLoader extends ClassLoader {
75        Object lock;
76        volatile int numFindClassCalled;
77
78        SyncTestClassLoader(Object o) {
79            this.lock = o;
80            numFindClassCalled = 0;
81        }
82
83        /*
84         * Byte array of bytecode equivalent to the following source code:
85         * public class TestClass {
86         * }
87         */
88        private byte[] classData = new byte[] {
89            -54, -2, -70, -66, 0, 0, 0, 49, 0, 13,
90            10, 0, 3, 0, 10, 7, 0, 11, 7, 0,
91            12, 1, 0, 6, 60, 105, 110, 105, 116, 62,
92            1, 0, 3, 40, 41, 86, 1, 0, 4, 67,
93            111, 100, 101, 1, 0, 15, 76, 105, 110, 101,
94            78, 117, 109, 98, 101, 114, 84, 97, 98, 108,
95            101, 1, 0, 10, 83, 111, 117, 114, 99, 101,
96            70, 105, 108, 101, 1, 0, 14, 84, 101, 115,
97            116, 67, 108, 97, 115, 115, 46, 106, 97, 118,
98            97, 12, 0, 4, 0, 5, 1, 0, 9, 84,
99            101, 115, 116, 67, 108, 97, 115, 115, 1, 0,
100            16, 106, 97, 118, 97, 47, 108, 97, 110, 103,
101            47, 79, 98, 106, 101, 99, 116, 0, 33, 0,
102            2, 0, 3, 0, 0, 0, 0, 0, 1, 0,
103            1, 0, 4, 0, 5, 0, 1, 0, 6, 0,
104            0, 0, 29, 0, 1, 0, 1, 0, 0, 0,
105            5, 42, -73, 0, 1, -79, 0, 0, 0, 1,
106            0, 7, 0, 0, 0, 6, 0, 1, 0, 0,
107            0, 1, 0, 1, 0, 8, 0, 0, 0, 2,
108            0, 9 };
109
110        protected Class findClass(String name) throws ClassNotFoundException {
111            try {
112                while (flag != 2) {
113                    synchronized (lock) {
114                        lock.wait();
115                    }
116                }
117            } catch (InterruptedException ie) {}
118
119            if (name.equals("TestClass")) {
120                numFindClassCalled++;
121                return defineClass(null, classData, 0, classData.length);
122            } else {
123                throw new ClassNotFoundException("Class " + name + " not found.");
124            }
125        }
126    }
127
128    static class SyncLoadTestThread extends Thread {
129        volatile boolean started;
130        ClassLoader cl;
131        Class cls;
132
133        SyncLoadTestThread(ClassLoader cl) {
134            this.cl = cl;
135        }
136
137        public void run() {
138            try {
139                started = true;
140                cls = Class.forName("TestClass", false, cl);
141            } catch (Exception ex) {
142                ex.printStackTrace();
143            }
144        }
145    }
146
147    /**
148     * Regression test for HARMONY-1939:
149     * 2 threads simultaneously run Class.forName() method for the same classname
150     * and the same classloader. It is expected that both threads succeed but
151     * class must be defined just once.
152     */
153    @TestInfo(
154          level = TestLevel.PARTIAL,
155          purpose = "Regression test.",
156          targets = {
157            @TestTarget(
158              methodName = "loadClass",
159              methodArgs = {java.lang.String.class}
160            )
161        })
162    public void _test_loadClass_concurrentLoad() throws Exception
163    {
164        Object lock = new Object();
165        SyncTestClassLoader cl = new SyncTestClassLoader(lock);
166        SyncLoadTestThread tt1 = new SyncLoadTestThread(cl);
167        SyncLoadTestThread tt2 = new SyncLoadTestThread(cl);
168        flag = 1;
169        tt1.start();
170        tt2.start();
171
172        while (!tt1.started && !tt2.started) {
173            Thread.sleep(100);
174        }
175
176        flag = 2;
177        synchronized (lock) {
178            lock.notifyAll();
179        }
180        tt1.join();
181        tt2.join();
182
183        assertSame("Bad or redefined class", tt1.cls, tt2.cls);
184        assertEquals("Both threads tried to define class", 1, cl.numFindClassCalled);
185    }
186
187    /**
188     * @tests java.lang.ClassLoader#getResource(java.lang.String)
189     */
190    @TestInfo(
191      level = TestLevel.PARTIAL,
192      purpose = "Verifies only positive case.",
193      targets = {
194        @TestTarget(
195          methodName = "getResource",
196          methodArgs = {java.lang.String.class}
197        )
198    })
199    public void test_getResourceLjava_lang_String() {
200        // Test for method java.net.URL
201        // java.lang.ClassLoader.getResource(java.lang.String)
202        java.net.URL u = ClassLoader.getSystemClassLoader().getResource("hyts_Foo.c");
203        assertNotNull("Unable to find resource", u);
204        java.io.InputStream is = null;
205        try {
206            is = u.openStream();
207            assertNotNull("Resource returned is invalid", is);
208            is.close();
209        } catch (java.io.IOException e) {
210            fail("IOException getting stream for resource : " + e.getMessage());
211        }
212    }
213
214    /**
215     * @tests java.lang.ClassLoader#getResourceAsStream(java.lang.String)
216     */
217    @TestInfo(
218      level = TestLevel.PARTIAL,
219      purpose = "Verifies only positive case.",
220      targets = {
221        @TestTarget(
222          methodName = "getResourceAsStream",
223          methodArgs = {java.lang.String.class}
224        )
225    })
226    public void test_getResourceAsStreamLjava_lang_String() {
227        // Test for method java.io.InputStream
228        // java.lang.ClassLoader.getResourceAsStream(java.lang.String)
229        // Need better test...
230
231        java.io.InputStream is = null;
232        assertNotNull("Failed to find resource: hyts_Foo.c", (is = ClassLoader
233                .getSystemClassLoader().getResourceAsStream("hyts_Foo.c")));
234        try {
235            is.close();
236        } catch (java.io.IOException e) {
237            fail("Exception during getResourceAsStream: " + e.toString());
238        }
239    }
240
241    /**
242     * @tests java.lang.ClassLoader#getSystemClassLoader()
243     */
244    @TestInfo(
245      level = TestLevel.COMPLETE,
246      purpose = "",
247      targets = {
248        @TestTarget(
249          methodName = "getSystemClassLoader",
250          methodArgs = {}
251        )
252    })
253    public void test_getSystemClassLoader() {
254        // Test for method java.lang.ClassLoader
255        // java.lang.ClassLoader.getSystemClassLoader()
256        ClassLoader cl = ClassLoader.getSystemClassLoader();
257        java.io.InputStream is = cl.getResourceAsStream("hyts_Foo.c");
258        assertNotNull("Failed to find resource from system classpath", is);
259        try {
260            is.close();
261        } catch (java.io.IOException e) {
262        }
263
264    }
265
266    /**
267     * @tests java.lang.ClassLoader#getSystemResource(java.lang.String)
268     */
269    @TestInfo(
270      level = TestLevel.COMPLETE,
271      purpose = "Doesn't verify functionality.",
272      targets = {
273        @TestTarget(
274          methodName = "getSystemResource",
275          methodArgs = {java.lang.String.class}
276        )
277    })
278    public void test_getSystemResourceLjava_lang_String() {
279        // Test for method java.net.URL
280        // java.lang.ClassLoader.getSystemResource(java.lang.String)
281        // Need better test...
282        assertNotNull("Failed to find resource: hyts_Foo.c", ClassLoader
283                .getSystemResource("hyts_Foo.c"));
284    }
285
286
287    //Regression Test for JIRA-2047
288    @TestInfo(
289      level = TestLevel.PARTIAL,
290      purpose = "Verifies only positive case.",
291      targets = {
292        @TestTarget(
293          methodName = "getResourceAsStream",
294          methodArgs = {java.lang.String.class}
295        )
296    })
297    public void _test_getResourceAsStream_withSharpChar() throws Exception {
298        /*
299         * The Harmony resource could not be found anywhere, so we take
300         * our own.
301         */
302        InputStream in = this.getClass().getClassLoader().getResourceAsStream(
303                "test#.properties" /* ClassTest.FILENAME */);
304        assertNotNull(in);
305        in.close();
306    }
307}
308
309class DynamicPolicy extends Policy {
310
311    public PermissionCollection pc;
312
313    @Override
314    public PermissionCollection getPermissions(ProtectionDomain pd) {
315        return pc;
316    }
317
318    @Override
319    public PermissionCollection getPermissions(CodeSource codesource) {
320        return pc;
321    }
322
323    @Override
324    public void refresh() {
325    }
326}
327
328class A {
329}
330
331class Ldr extends ClassLoader {
332    @SuppressWarnings("deprecation")
333    public Class<?> define() throws Exception {
334        Package p = getClass().getPackage();
335        String path = p == null ? "" : p.getName().replace('.', File.separatorChar)
336                + File.separator;
337        InputStream is = getResourceAsStream(path + "A.class");
338        byte[] buf = new byte[512];
339        int len = is.read(buf);
340        return defineClass("org.apache.harmony.luni.tests.java.lang.A", buf, 0, len);
341    }
342}
343