Return-Path: Delivered-To: apmail-incubator-harmony-commits-archive@www.apache.org Received: (qmail 91097 invoked from network); 15 Mar 2006 12:26:03 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur.apache.org with SMTP; 15 Mar 2006 12:26:03 -0000 Received: (qmail 61894 invoked by uid 500); 15 Mar 2006 12:25:59 -0000 Delivered-To: apmail-incubator-harmony-commits-archive@incubator.apache.org Received: (qmail 61843 invoked by uid 500); 15 Mar 2006 12:25:59 -0000 Mailing-List: contact harmony-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: harmony-dev@incubator.apache.org Delivered-To: mailing list harmony-commits@incubator.apache.org Received: (qmail 61791 invoked by uid 99); 15 Mar 2006 12:25:58 -0000 Received: from asf.osuosl.org (HELO asf.osuosl.org) (140.211.166.49) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 15 Mar 2006 04:25:58 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [209.237.227.194] (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.29) with SMTP; Wed, 15 Mar 2006 04:25:53 -0800 Received: (qmail 90034 invoked by uid 65534); 15 Mar 2006 12:25:24 -0000 Message-ID: <20060315122524.89990.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r386058 [22/49] - in /incubator/harmony/enhanced/classlib/trunk: make/ modules/archive/make/common/ modules/archive/src/test/java/tests/ modules/archive/src/test/java/tests/api/ modules/archive/src/test/java/tests/api/java/ modules/archive/... Date: Wed, 15 Mar 2006 11:47:39 -0000 To: harmony-commits@incubator.apache.org From: tellison@apache.org X-Mailer: svnmailer-1.0.7 X-Virus-Checked: Checked by ClamAV on apache.org X-Spam-Rating: minotaur.apache.org 1.6.2 0/1000/N Added: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/SystemTest.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/SystemTest.java?rev=386058&view=auto ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/SystemTest.java (added) +++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/SystemTest.java Wed Mar 15 03:46:17 2006 @@ -0,0 +1,343 @@ +/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.java.lang; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.PrintStream; +import java.util.Properties; + +public class SystemTest extends junit.framework.TestCase { + + static boolean flag = false; + + static boolean ranFinalize = false; + + /** + * @tests java.lang.System#setIn(java.io.InputStream) + */ + public void test_setInLjava_io_InputStream() { + InputStream orgIn = System.in; + InputStream in = new ByteArrayInputStream(new byte[0]); + System.setIn(in); + assertTrue("in not set", System.in == in); + System.setIn(orgIn); + } + + /** + * @tests java.lang.System#setOut(java.io.PrintStream) + */ + public void test_setOutLjava_io_PrintStream() { + PrintStream orgOut = System.out; + PrintStream out = new PrintStream(new ByteArrayOutputStream()); + System.setOut(out); + assertTrue("out not set", System.out == out); + System.setOut(orgOut); + } + + /** + * @tests java.lang.System#setErr(java.io.PrintStream) + */ + public void test_setErrLjava_io_PrintStream() { + PrintStream orgErr = System.err; + PrintStream err = new PrintStream(new ByteArrayOutputStream()); + System.setErr(err); + assertTrue("err not set", System.err == err); + System.setErr(orgErr); + } + + /** + * @tests java.lang.System#arraycopy(java.lang.Object, int, + * java.lang.Object, int, int) + */ + public void test_arraycopyLjava_lang_ObjectILjava_lang_ObjectII() { + // Test for method void java.lang.System.arraycopy(java.lang.Object, + // int, java.lang.Object, int, int) + Integer a[] = new Integer[20]; + Integer b[] = new Integer[20]; + int i = 0; + while (i < a.length) { + a[i] = new Integer(i); + ++i; + } + System.arraycopy(a, 0, b, 0, a.length); + for (i = 0; i < a.length; i++) + assertTrue("Copied elements incorrectly", a[i].equals(b[i])); + + /* Non primitive array types don't need to be identical */ + String[] source1 = new String[] { "element1" }; + Object[] dest1 = new Object[1]; + System.arraycopy(source1, 0, dest1, 0, dest1.length); + assertTrue("Invalid copy 1", dest1[0] == source1[0]); + + char[][] source = new char[][] { { 'H', 'e', 'l', 'l', 'o' }, + { 'W', 'o', 'r', 'l', 'd' } }; + char[][] dest = new char[2][]; + System.arraycopy(source, 0, dest, 0, dest.length); + assertTrue("Invalid copy 2", dest[0] == source[0] + && dest[1] == source[1]); + } + + /** + * @tests java.lang.System#currentTimeMillis() + */ + public void test_currentTimeMillis() { + // Test for method long java.lang.System.currentTimeMillis() + try { + long firstRead = System.currentTimeMillis(); + try { + Thread.sleep(150); + } catch (InterruptedException e) { + } + long secondRead = System.currentTimeMillis(); + assertTrue("Incorrect times returned: " + firstRead + ", " + + secondRead, firstRead < secondRead); + } catch (Exception e) { + System.out.println("Exception during test: " + e.toString()); + } + } + + /** + * @tests java.lang.System#exit(int) + */ + public void test_exitI() { + // Test for method void java.lang.System.exit(int) + // Tested in destructive test: Test_System_Exit ??? + } + + /** + * @tests java.lang.System#getProperties() + */ + public void test_getProperties() { + // Test for method java.util.Properties java.lang.System.getProperties() + Properties p = System.getProperties(); + assertTrue("Incorrect properties returned", p.getProperty( + "java.version").indexOf("1.", 0) >= 0); + + // Ensure spec'ed properties are non-null. See System.getProperties() + // spec. + String[] props = { "java.version", "java.vendor", "java.vendor.url", + "java.home", "java.vm.specification.version", + "java.vm.specification.vendor", "java.vm.specification.name", + "java.vm.version", "java.vm.vendor", "java.vm.name", + "java.specification.name", "java.specification.vendor", + "java.specification.name", "java.class.version", + "java.class.path", "java.ext.dirs", "os.name", "os.arch", + "os.version", "file.separator", "path.separator", + "line.separator", "user.name", "user.home", "user.dir", }; + for (int i = 0; i < props.length; i++) { + assertTrue(props[i], System.getProperty(props[i]) != null); + } + } + + /** + * @tests java.lang.System#getProperty(java.lang.String) + */ + public void test_getPropertyLjava_lang_String() { + // Test for method java.lang.String + // java.lang.System.getProperty(java.lang.String) + assertTrue("Failed to return correct property value", System + .getProperty("java.version").indexOf("1.", 0) >= 0); + + boolean is8859_1 = true; + String encoding = System.getProperty("file.encoding"); + byte[] bytes = new byte[128]; + char[] chars = new char[128]; + for (int i = 0; i < bytes.length; i++) { + bytes[i] = (byte) (i + 128); + chars[i] = (char) (i + 128); + } + String charResult = new String(bytes); + byte[] byteResult = new String(chars).getBytes(); + if (charResult.length() == 128 && byteResult.length == 128) { + for (int i = 0; i < bytes.length; i++) { + if (charResult.charAt(i) != (char) (i + 128) + || byteResult[i] != (byte) (i + 128)) + is8859_1 = false; + } + } else + is8859_1 = false; + String[] possibles = new String[] { "ISO8859_1", "8859_1", "ISO8859-1", + "ISO-8859-1", "ISO_8859-1", "ISO_8859-1:1978", "ISO-IR-100", + "LATIN1", "CSISOLATIN1" }; + boolean found8859_1 = false; + for (int i = 0; i < possibles.length; i++) { + if (possibles[i].equals(encoding)) { + found8859_1 = true; + break; + } + } + assertTrue("Wrong encoding: " + encoding, !is8859_1 || found8859_1); + } + + /** + * @tests java.lang.System#getProperty(java.lang.String, java.lang.String) + */ + public void test_getPropertyLjava_lang_StringLjava_lang_String() { + // Test for method java.lang.String + // java.lang.System.getProperty(java.lang.String, java.lang.String) + assertTrue("Failed to return correct property value: " + + System.getProperty("java.version", "99999"), System + .getProperty("java.version", "99999").indexOf("1.", 0) >= 0); + assertTrue("Failed to return correct property value", System + .getProperty("bogus.prop", "bogus").equals("bogus")); + } + + /** + * @tests java.lang.System#setProperty(java.lang.String, java.lang.String) + */ + public void test_setPropertyLjava_lang_StringLjava_lang_String() { + // Test for method java.lang.String + // java.lang.System.setProperty(java.lang.String, java.lang.String) + + assertTrue("Failed to return null", System.setProperty("testing", + "value1") == null); + assertTrue("Failed to return old value", System.setProperty("testing", + "value2") == "value1"); + assertTrue("Failed to find value", + System.getProperty("testing") == "value2"); + + boolean exception = false; + try { + System.setProperty("", "default"); + } catch (IllegalArgumentException e) { + exception = true; + } + assertTrue("Expected IllegalArgumentException", exception); + } + + /** + * @tests java.lang.System#getSecurityManager() + */ + public void test_getSecurityManager() { + // Test for method java.lang.SecurityManager + // java.lang.System.getSecurityManager() + assertTrue("Returned incorrect SecurityManager", System + .getSecurityManager() == null); + } + + /** + * @tests java.lang.System#identityHashCode(java.lang.Object) + */ + public void test_identityHashCodeLjava_lang_Object() { + // Test for method int + // java.lang.System.identityHashCode(java.lang.Object) + Object o = new Object(); + String s = "Gabba"; + assertTrue("Nonzero returned for null", + System.identityHashCode(null) == 0); + assertTrue("Nonequal has returned for Object", System + .identityHashCode(o) == o.hashCode()); + assertTrue("Same as usual hash returned for String", System + .identityHashCode(s) != s.hashCode()); + } + + /** + * @tests java.lang.System#runFinalization() + */ + public void test_runFinalization() { + // Test for method void java.lang.System.runFinalization() + + flag = true; + createInstance(); + int count = 10; + // the gc below likely bogosifies the test, but will have to do for + // the moment + while (!ranFinalize && count-- > 0) { + System.gc(); + System.runFinalization(); + } + assertTrue("Failed to run finalization", ranFinalize); + } + + /** + * @tests java.lang.System#runFinalizersOnExit(boolean) + */ + public void test_runFinalizersOnExitZ() { + // Test for method void java.lang.System.runFinalizersOnExit(boolean) + // Can we call the method at least? + try { + System.runFinalizersOnExit(true); + } catch (Throwable t) { + fail("Failed to set runFinalizersOnExit"); + } + assertTrue("Passed runFinalizersOnExit", true); + } + + /** + * @tests java.lang.System#setProperties(java.util.Properties) + */ + public void test_setPropertiesLjava_util_Properties() { + // Test for method void + // java.lang.System.setProperties(java.util.Properties) + + Properties orgProps = System.getProperties(); + java.util.Properties tProps = new java.util.Properties(); + tProps.put("test.prop", "this is a test property"); + tProps.put("bogus.prop", "bogus"); + System.setProperties(tProps); + try { + assertTrue("Failed to set properties", System.getProperties() + .getProperty("test.prop").equals("this is a test property")); + } finally { + // restore the original properties + System.setProperties(orgProps); + } + } + + /** + * @tests java.lang.System#setSecurityManager(java.lang.SecurityManager) + */ + public void test_setSecurityManagerLjava_lang_SecurityManager() { + // Test for method void + // java.lang.System.setSecurityManager(java.lang.SecurityManager) + // tested in System_Destructive ?? + } + + /** + * Sets up the fixture, for example, open a network connection. This method + * is called before a test is executed. + */ + protected void setUp() { + flag = false; + ranFinalize = false; + } + + /** + * Tears down the fixture, for example, close a network connection. This + * method is called after a test is executed. + */ + protected void tearDown() { + // System.setProperties(orgProps); + } + + protected SystemTest createInstance() { + return new SystemTest("FT"); + } + + protected void finalize() { + if (flag) + ranFinalize = true; + } + + public SystemTest() { + } + + public SystemTest(String name) { + super(name); + } +} Added: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/ThreadDeathTest.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/ThreadDeathTest.java?rev=386058&view=auto ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/ThreadDeathTest.java (added) +++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/ThreadDeathTest.java Wed Mar 15 03:46:17 2006 @@ -0,0 +1,44 @@ +/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.java.lang; + +public class ThreadDeathTest extends junit.framework.TestCase { + + /** + * @tests java.lang.ThreadDeath#ThreadDeath() + */ + public void test_Constructor() { + // Test for method java.lang.ThreadDeath() + + ThreadDeath td = new ThreadDeath(); + + assertTrue(" Should be a Threaddeath", td instanceof ThreadDeath); + } + + /** + * Sets up the fixture, for example, open a network connection. This method + * is called before a test is executed. + */ + protected void setUp() { + } + + /** + * Tears down the fixture, for example, close a network connection. This + * method is called after a test is executed. + */ + protected void tearDown() { + } +} Added: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/ThreadGroupTest.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/ThreadGroupTest.java?rev=386058&view=auto ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/ThreadGroupTest.java (added) +++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/ThreadGroupTest.java Wed Mar 15 03:46:17 2006 @@ -0,0 +1,1499 @@ +/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.java.lang; + +import java.util.Vector; + +public class ThreadGroupTest extends junit.framework.TestCase { + + class MyThread extends Thread { + public volatile int heartBeat = 0; + + public MyThread(ThreadGroup group, String name) + throws SecurityException, IllegalThreadStateException { + super(group, name); + } + + public void run() { + while (true) { + heartBeat++; + try { + Thread.sleep(50); + } catch (InterruptedException e) { + } + } + } + + public boolean isActivelyRunning() { + long MAX_WAIT = 100; + return isActivelyRunning(MAX_WAIT); + } + + public boolean isActivelyRunning(long maxWait) { + int beat = heartBeat; + long start = System.currentTimeMillis(); + do { + Thread.yield(); + int beat2 = heartBeat; + if (beat != beat2) + return true; + } while (System.currentTimeMillis() - start < maxWait); + return false; + } + + } + + private ThreadGroup rootThreadGroup = null; + + private ThreadGroup initialThreadGroup = null; + + /** + * @tests java.lang.ThreadGroup#ThreadGroup(java.lang.String) + */ + public void test_ConstructorLjava_lang_String() { + // Test for method java.lang.ThreadGroup(java.lang.String) + + // Unfortunately we have to use other APIs as well as we test the + // constructor + + ThreadGroup newGroup = null; + ThreadGroup initial = getInitialThreadGroup(); + final String name = "Test name"; + newGroup = new ThreadGroup(name); + assertTrue( + "Has to be possible to create a subgroup of current group using simple constructor", + newGroup.getParent() == initial); + assertTrue("Name has to be correct", newGroup.getName().equals(name)); + + // cleanup + newGroup.destroy(); + + } + + /** + * @tests java.lang.ThreadGroup#ThreadGroup(java.lang.ThreadGroup, + * java.lang.String) + */ + public void test_ConstructorLjava_lang_ThreadGroupLjava_lang_String() { + // Test for method java.lang.ThreadGroup(java.lang.ThreadGroup, + // java.lang.String) + + // Unfortunately we have to use other APIs as well as we test the + // constructor + + ThreadGroup newGroup = null; + + try { + newGroup = new ThreadGroup(null, null); + } catch (NullPointerException e) { + } + assertTrue("Can't create a ThreadGroup with a null parent", + newGroup == null); + + newGroup = new ThreadGroup(getInitialThreadGroup(), null); + assertTrue("Has to be possible to create a subgroup of current group", + newGroup.getParent() == Thread.currentThread().getThreadGroup()); + + // Lets start all over + newGroup.destroy(); + + newGroup = new ThreadGroup(getRootThreadGroup(), "a name here"); + assertTrue("Has to be possible to create a subgroup of root group", + newGroup.getParent() == getRootThreadGroup()); + + // Lets start all over + newGroup.destroy(); + + try { + newGroup = new ThreadGroup(newGroup, "a name here"); + } catch (IllegalThreadStateException e) { + newGroup = null; + } + ; + assertTrue("Can't create a subgroup of a destroyed group", + newGroup == null); + } + + /** + * @tests java.lang.ThreadGroup#activeCount() + */ + public void test_activeCount() { + // Test for method int java.lang.ThreadGroup.activeCount() + ThreadGroup tg = new ThreadGroup("activeCount"); + Thread t1 = new Thread(tg, new Runnable() { + public void run() { + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + } + } + }); + int count = tg.activeCount(); + assertTrue("wrong active count: " + count, count == 1); + t1.start(); + count = tg.activeCount(); + assertTrue("wrong active count: " + count, count == 1); + t1.interrupt(); + try { + t1.join(); + } catch (InterruptedException e) { + } + } + + /** + * @tests java.lang.ThreadGroup#checkAccess() + */ + public void test_checkAccess() { + // Test for method void java.lang.ThreadGroup.checkAccess() + + final ThreadGroup originalCurrent = getInitialThreadGroup(); + ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group"); + + SecurityManager currentManager = System.getSecurityManager(); + boolean passed = true; + + try { + if (currentManager != null) + testRoot.checkAccess(); + } catch (SecurityException se) { + passed = false; + } + ; + + assertTrue("CheckAccess is no-op with no Securitymanager", passed); + + testRoot.destroy(); + + } + + /** + * @tests java.lang.ThreadGroup#destroy() + */ + public void test_destroy() { + // Test for method void java.lang.ThreadGroup.destroy() + + final ThreadGroup originalCurrent = getInitialThreadGroup(); + ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group"); + final int DEPTH = 4; + final Vector subgroups = buildRandomTreeUnder(testRoot, DEPTH); + + // destroy them all + testRoot.destroy(); + + for (int i = 0; i < subgroups.size(); i++) { + ThreadGroup child = (ThreadGroup) subgroups.elementAt(i); + assertTrue("Destroyed child can't have children", child + .activeCount() == 0); + boolean passed = false; + try { + child.destroy(); + } catch (IllegalThreadStateException e) { + passed = true; + } + ; + assertTrue("Destroyed child can't be destroyed again", passed); + } + + testRoot = new ThreadGroup(originalCurrent, "Test group (daemon)"); + testRoot.setDaemon(true); + + ThreadGroup child = new ThreadGroup(testRoot, "daemon child"); + + // If we destroy the last daemon's child, the daemon should get destroyed + // as well + child.destroy(); + + boolean passed = false; + try { + child.destroy(); + } catch (IllegalThreadStateException e) { + passed = true; + } + ; + assertTrue("Daemon should have been destroyed already", passed); + + passed = false; + try { + testRoot.destroy(); + } catch (IllegalThreadStateException e) { + passed = true; + } + ; + assertTrue("Daemon parent should have been destroyed automatically", + passed); + + assertTrue( + "Destroyed daemon's child should not be in daemon's list anymore", + !arrayIncludes(groups(testRoot), child)); + assertTrue("Destroyed daemon should not be in parent's list anymore", + !arrayIncludes(groups(originalCurrent), testRoot)); + + testRoot = new ThreadGroup(originalCurrent, "Test group (daemon)"); + testRoot.setDaemon(true); + Thread noOp = new Thread(testRoot, null, "no-op thread") { + public void run() { + } + }; + noOp.start(); + + // Wait for the no-op thread to run inside daemon ThreadGroup + try { + noOp.join(); + } catch (InterruptedException ie) { + fail("Should not be interrupted"); + } + ; + + passed = false; + try { + child.destroy(); + } catch (IllegalThreadStateException e) { + passed = true; + } + ; + assertTrue( + "Daemon group should have been destroyed already when last thread died", + passed); + + testRoot = new ThreadGroup(originalCurrent, "Test group (daemon)"); + noOp = new Thread(testRoot, null, "no-op thread") { + public void run() { + try { + Thread.sleep(500); + } catch (InterruptedException ie) { + fail("Should not be interrupted"); +// // We have our own assert +// myassertTrue("Should not be interrupted", false); + } + ; + } + }; + + // Has to execute the next lines in an interval < the sleep interval of + // the no-op thread + noOp.start(); + passed = false; + try { + testRoot.destroy(); + } catch (IllegalThreadStateException its) { + passed = true; + } + assertTrue("Can't destroy a ThreadGroup that has threads", passed); + + // But after the thread dies, we have to be able to destroy the thread + // group + try { + noOp.join(); + } catch (InterruptedException ie) { + fail("Should not be interrupted"); + } + ; + passed = true; + try { + testRoot.destroy(); + } catch (IllegalThreadStateException its) { + passed = false; + } + assertTrue( + "Should be able to destroy a ThreadGroup that has no threads", + passed); + + } + + /** + * @tests java.lang.ThreadGroup#destroy() + */ + public void test_destroy_subtest0() { + ThreadGroup group1 = new ThreadGroup("test_destroy_subtest0"); + group1.destroy(); + try { + Thread t = new Thread(group1, "test_destroy_subtest0"); + fail("should throw IllegalThreadStateException"); + } catch (IllegalThreadStateException e) { + } + } + + /** + * @tests java.lang.ThreadGroup#getMaxPriority() + */ + public void test_getMaxPriority() { + // Test for method int java.lang.ThreadGroup.getMaxPriority() + + final ThreadGroup originalCurrent = getInitialThreadGroup(); + ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group"); + + boolean passed = true; + passed = true; + try { + testRoot.setMaxPriority(Thread.MIN_PRIORITY); + } catch (IllegalArgumentException iae) { + passed = false; + } + assertTrue("Should be able to set piority", passed); + + assertTrue("New value should be the same as we set", testRoot + .getMaxPriority() == Thread.MIN_PRIORITY); + + testRoot.destroy(); + + } + + /** + * @tests java.lang.ThreadGroup#getName() + */ + public void test_getName() { + // Test for method java.lang.String java.lang.ThreadGroup.getName() + + final ThreadGroup originalCurrent = getInitialThreadGroup(); + final String name = "Test group"; + final ThreadGroup testRoot = new ThreadGroup(originalCurrent, name); + + assertTrue("Setting a name&getting does not work", testRoot.getName() + .equals(name)); + + testRoot.destroy(); + + } + + static ThreadGroup checkAccessGroup = null; + + /** + * @tests java.lang.ThreadGroup#getParent() + */ + public void test_getParent() { + // Test for method java.lang.ThreadGroup + // java.lang.ThreadGroup.getParent() + + final ThreadGroup originalCurrent = getInitialThreadGroup(); + ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group"); + + assertTrue("Parent is wrong", testRoot.getParent() == originalCurrent); + + // Create some groups, nested some levels. + final int TOTAL_DEPTH = 5; + ThreadGroup current = testRoot; + Vector groups = new Vector(); + // To maintain the invariant that a thread in the Vector is parent + // of the next one in the collection (and child of the previous one) + groups.addElement(testRoot); + + for (int i = 0; i < TOTAL_DEPTH; i++) { + current = new ThreadGroup(current, "level " + i); + groups.addElement(current); + } + + // Now we walk the levels down, checking if parent is ok + for (int i = 1; i < groups.size(); i++) { + current = (ThreadGroup) groups.elementAt(i); + ThreadGroup previous = (ThreadGroup) groups.elementAt(i - 1); + assertTrue("Parent is wrong", current.getParent() == previous); + } + + SecurityManager m = new SecurityManager() { + public void checkAccess(ThreadGroup group) { + checkAccessGroup = group; + } + }; + ThreadGroup parent; + try { + // To see if it checks Thread creation with our SecurityManager + System.setSecurityManager(m); + parent = testRoot.getParent(); + } finally { + // restore original, no side-effects + System.setSecurityManager(null); + } + assertTrue("checkAccess with incorrect group", + checkAccessGroup == parent); + + testRoot.destroy(); + } + + /** + * @tests java.lang.ThreadGroup#isDaemon() + */ + public void test_isDaemon() { + // Test for method boolean java.lang.ThreadGroup.isDaemon() + + daemonTests(); + + } + + /** + * @tests java.lang.ThreadGroup#list() + */ + public void test_list() { + // Test for method void java.lang.ThreadGroup.list() + + final ThreadGroup originalCurrent = getInitialThreadGroup(); + // wipeSideEffectThreads destroy all side effect of threads created in + // java.lang.Thread + boolean result = wipeSideEffectThreads(originalCurrent); + if (result == false) + System.out.println("wipe threads in test_list() not successful"); + final ThreadGroup testRoot = new ThreadGroup(originalCurrent, + "Test group"); + + // First save the original System.out + java.io.PrintStream originalOut = System.out; + + try { + java.io.ByteArrayOutputStream contentsStream = new java.io.ByteArrayOutputStream( + 100); + java.io.PrintStream newOut = new java.io.PrintStream(contentsStream); + + // We have to "redirect" System.out to test the method 'list' + System.setOut(newOut); + + originalCurrent.list(); + byte[] contents = contentsStream.toByteArray(); + + /* + * The output has to look like this + * + * java.lang.ThreadGroup[name=main,maxpri=10] Thread[main,5,main] + * java.lang.ThreadGroup[name=Test group,maxpri=10] + * + */ + + boolean passed = verifyThreadList(originalCurrent, testRoot, + contents); + + assertTrue( + "Either 'list' is wrong or other tests are leaving side-effects.\n" + + "Result from list:\n " + "-----------------\n " + + new String(contents, 0, contents.length) + + "\n-----------------\n ", passed); + + // Do proper cleanup + testRoot.destroy(); + + } finally { + // No matter what, we need to restore the original System.out + System.setOut(originalOut); + } + + } + + /** + * @tests java.lang.ThreadGroup#parentOf(java.lang.ThreadGroup) + */ + public void test_parentOfLjava_lang_ThreadGroup() { + // Test for method boolean + // java.lang.ThreadGroup.parentOf(java.lang.ThreadGroup) + + final ThreadGroup originalCurrent = getInitialThreadGroup(); + final ThreadGroup testRoot = new ThreadGroup(originalCurrent, + "Test group"); + final int DEPTH = 4; + buildRandomTreeUnder(testRoot, DEPTH); + + final ThreadGroup[] allChildren = allGroups(testRoot); + for (int i = 0; i < allChildren.length; i++) { + assertTrue("Have to be parentOf all children", testRoot + .parentOf((ThreadGroup) allChildren[i])); + } + + assertTrue("Have to be parentOf itself", testRoot.parentOf(testRoot)); + + testRoot.destroy(); + assertTrue("Parent can't have test group as subgroup anymore", + !arrayIncludes(groups(testRoot.getParent()), testRoot)); + + try { + System.setSecurityManager(new SecurityManager()); + assertTrue("Should not be parent", !testRoot + .parentOf(originalCurrent)); + } finally { + System.setSecurityManager(null); + } + } + + /** + * @tests java.lang.ThreadGroup#resume() + */ + public void test_resume() throws OutOfMemoryError { + // Test for method void java.lang.ThreadGroup.resume() + + final ThreadGroup originalCurrent = getInitialThreadGroup(); + + final ThreadGroup testRoot = new ThreadGroup(originalCurrent, + "Test group"); + final int DEPTH = 2; + buildRandomTreeUnder(testRoot, DEPTH); + + final int THREADS_PER_GROUP = 2; + final Vector threads = populateGroupsWithThreads(testRoot, + THREADS_PER_GROUP); + + assertTrue("Internal error when populating ThreadGroups", testRoot + .activeCount() == threads.size()); + + boolean[] isResumed = null; + try { + try { + for (int i = 0; i < threads.size(); i++) { + Thread t = (Thread) threads.elementAt(i); + t.start(); + t.suspend(); + } + } catch (OutOfMemoryError e) { + for (int i = 0; i < threads.size(); i++) { + Thread t = (Thread) threads.elementAt(i); + t.resume(); + t.stop(); // deprecated but effective + } + throw e; + } + + // Now that they are all suspended, let's resume the ThreadGroup + testRoot.resume(); + + // Give them some time to really resume + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + fail("Should not have been interrupted"); + } + + isResumed = new boolean[threads.size()]; + boolean failed = false; + for (int i = 0; i < isResumed.length; i++) { + MyThread t = (MyThread) threads.elementAt(i); + if (!failed) { // if one failed, don't waste time checking the + // rest + isResumed[i] = t.isActivelyRunning(5000); + failed = failed | (!isResumed[i]); + } + t.stop(); // deprecated but effective + } + + // Give them some time to really die + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + fail("Should not have been interrupted"); + } + } finally { + // Make sure we do cleanup before returning + testRoot.destroy(); + } + + for (int i = 0; i < isResumed.length; i++) { + assertTrue("Thread " + threads.elementAt(i) + + " was not running when it was killed", isResumed[i]); + } + + assertTrue("Method destroy must have problems", + testRoot.activeCount() == 0); + + } + + /** + * @tests java.lang.ThreadGroup#setDaemon(boolean) + */ + public void test_setDaemonZ() { + // Test for method void java.lang.ThreadGroup.setDaemon(boolean) + + daemonTests(); + + } + + /** + * @tests java.lang.ThreadGroup#setMaxPriority(int) + */ + public void test_setMaxPriorityI() { + // Test for method void java.lang.ThreadGroup.setMaxPriority(int) + + final ThreadGroup originalCurrent = getInitialThreadGroup(); + ThreadGroup testRoot = new ThreadGroup(originalCurrent, "Test group"); + + boolean passed; + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + int currentMax = testRoot.getMaxPriority(); + testRoot.setMaxPriority(Thread.MAX_PRIORITY + 1); + passed = testRoot.getMaxPriority() == currentMax; + assertTrue( + "setMaxPriority: Any value higher than the current one is ignored. Before: " + + currentMax + " , after: " + testRoot.getMaxPriority(), + passed); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + currentMax = testRoot.getMaxPriority(); + testRoot.setMaxPriority(Thread.MIN_PRIORITY - 1); + passed = testRoot.getMaxPriority() == Thread.MIN_PRIORITY; + assertTrue( + "setMaxPriority: Any value smaller than MIN_PRIORITY is adjusted to MIN_PRIORITY. Before: " + + currentMax + " , after: " + testRoot.getMaxPriority(), + passed); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + testRoot.destroy(); + testRoot = new ThreadGroup(originalCurrent, "Test group"); + + // Create some groups, nested some levels. Each level will have maxPrio + // 1 unit smaller than the parent's. However, there can't be a group + // with priority < Thread.MIN_PRIORITY + final int TOTAL_DEPTH = testRoot.getMaxPriority() - Thread.MIN_PRIORITY + - 2; + ThreadGroup current = testRoot; + for (int i = 0; i < TOTAL_DEPTH; i++) { + current = new ThreadGroup(current, "level " + i); + } + + // Now we walk the levels down, changing the maxPrio and later verifying + // that the value is indeed 1 unit smaller than the parent's maxPrio. + int maxPrio, parentMaxPrio; + current = testRoot; + + // To maintain the invariant that when we are to modify a child, + // its maxPriority is always 1 unit smaller than its parent's. + // We have to set it for the root manually, and the loop does the rest + // for all the other sub-levels + current.setMaxPriority(current.getParent().getMaxPriority() - 1); + + for (int i = 0; i < TOTAL_DEPTH; i++) { + maxPrio = current.getMaxPriority(); + parentMaxPrio = current.getParent().getMaxPriority(); + + ThreadGroup[] children = groups(current); + assertTrue("Can only have 1 subgroup", children.length == 1); + current = children[0]; + assertTrue( + "Had to be 1 unit smaller than parent's priority in iteration=" + + i + " checking->" + current, + maxPrio == parentMaxPrio - 1); + current.setMaxPriority(maxPrio - 1); + + // The next test is sort of redundant, since in next iteration it + // will be the parent tGroup, so the test will be done. + assertTrue("Had to be possible to change max priority", current + .getMaxPriority() == maxPrio - 1); + } + + assertTrue( + "Priority of leaf child group has to be much smaller than original root group", + current.getMaxPriority() == testRoot.getMaxPriority() + - TOTAL_DEPTH); + + testRoot.destroy(); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + passed = true; + testRoot = new ThreadGroup(originalCurrent, "Test group"); + try { + testRoot.setMaxPriority(Thread.MAX_PRIORITY); + } catch (IllegalArgumentException iae) { + passed = false; + } + assertTrue( + "Max Priority = Thread.MAX_PRIORITY should be possible if the test is run with default system ThreadGroup as root", + passed); + testRoot.destroy(); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + passed = true; + testRoot = new ThreadGroup(originalCurrent, "Test group"); + System.setSecurityManager(new SecurityManager()); + try { + try { + testRoot.setMaxPriority(Thread.MIN_PRIORITY); + } catch (IllegalArgumentException iae) { + passed = false; + } + } finally { + System.setSecurityManager(null); + } + assertTrue( + "Min Priority = Thread.MIN_PRIORITY should be possible, always", + passed); + testRoot.destroy(); + + try { + System.setSecurityManager(new SecurityManager()); + originalCurrent.setMaxPriority(Thread.MAX_PRIORITY); + } finally { + System.setSecurityManager(null); + } + } + + /** + * @tests java.lang.ThreadGroup#stop() + */ + public void test_stop() throws OutOfMemoryError { + // Test for method void java.lang.ThreadGroup.stop() + + final ThreadGroup originalCurrent = getInitialThreadGroup(); + + final ThreadGroup testRoot = new ThreadGroup(originalCurrent, + "Test group"); + final int DEPTH = 2; + buildRandomTreeUnder(testRoot, DEPTH); + + final int THREADS_PER_GROUP = 2; + final Vector threads = populateGroupsWithThreads(testRoot, + THREADS_PER_GROUP); + + try { + for (int i = 0; i < threads.size(); i++) { + Thread t = (Thread) threads.elementAt(i); + t.start(); + } + } catch (OutOfMemoryError e) { + for (int i = 0; i < threads.size(); i++) { + Thread t = (Thread) threads.elementAt(i); + t.stop(); // deprecated but effective + } + throw e; + } + + // Now that they are all running, let's stop the ThreadGroup + testRoot.stop(); + + // stop is an async call. The thread may take a while to stop. We have + // to wait for all of them to stop. However, if stop does not work, + // we'd have to wait forever. So, we wait with a timeout, and if the + // Thread is still alive, we assume stop for ThreadGroups does not + // work. How much we wait (timeout) is very important + boolean passed = true; + for (int i = 0; i < threads.size(); i++) { + Thread t = (Thread) threads.elementAt(i); + try { + // We wait 5000 ms per Thread, but due to scheduling it may + // take a while to run + t.join(5000); + } catch (InterruptedException ie) { + fail("Should not be interrupted"); + } + if (t.isAlive()) { + passed = false; + break; + } + } + + // To make sure that even if we fail, we exit in a clean state + testRoot.destroy(); + + assertTrue("Thread should be dead by now", passed); + + assertTrue("Method destroy (or wipeAllThreads) must have problems", + testRoot.activeCount() == 0); + + } + + /** + * @tests java.lang.ThreadGroup#suspend() + */ + public void test_suspend() throws OutOfMemoryError { + // Test for method void java.lang.ThreadGroup.suspend() + + final ThreadGroup originalCurrent = getInitialThreadGroup(); + + final ThreadGroup testRoot = new ThreadGroup(originalCurrent, + "Test group"); + final int DEPTH = 2; + buildRandomTreeUnder(testRoot, DEPTH); + + final int THREADS_PER_GROUP = 2; + final Vector threads = populateGroupsWithThreads(testRoot, + THREADS_PER_GROUP); + + boolean passed = false; + try { + try { + for (int i = 0; i < threads.size(); i++) { + Thread t = (Thread) threads.elementAt(i); + t.start(); + } + } catch (OutOfMemoryError e) { + for (int i = 0; i < threads.size(); i++) { + Thread t = (Thread) threads.elementAt(i); + t.stop(); // deprecated but effective + } + throw e; + } + + // Now that they are all running, let's suspend the ThreadGroup + testRoot.suspend(); + + passed = allSuspended(threads); + assertTrue("Should be able to wipe all threads (allSuspended=" + + passed + ")", wipeAllThreads(testRoot)); + } finally { + + // We can't destroy a ThreadGroup if we do not make sure it has no + // threads at all + + // Make sure we cleanup before returning from the method + testRoot.destroy(); + } + assertTrue("All threads should be suspended", passed); + + assertTrue("Method destroy (or wipeAllThreads) must have problems", + testRoot.activeCount() == 0); + + } + + /** + * @tests java.lang.ThreadGroup#toString() + */ + public void test_toString() { + // Test for method java.lang.String java.lang.ThreadGroup.toString() + + final ThreadGroup originalCurrent = getInitialThreadGroup(); + final String tGroupName = "Test group"; + + // Our own subclass + class MyThreadGroup extends ThreadGroup { + // Have to define a constructor since there's no default one + public MyThreadGroup(ThreadGroup parent, String name) { + super(parent, name); + } + } + ; + + ThreadGroup testRoot = new MyThreadGroup(originalCurrent, tGroupName); + final String toString = testRoot.toString(); + + StringBuffer expectedResult = new StringBuffer(); + expectedResult.append(testRoot.getClass().getName()); + expectedResult.append("[name="); + expectedResult.append(tGroupName); + expectedResult.append(",maxpri="); + expectedResult.append(testRoot.getMaxPriority()); + expectedResult.append("]"); + + String expectedValue = expectedResult.toString(); + + assertTrue("toString does not follow the Java language spec.", toString + .equals(expectedValue)); + + testRoot.destroy(); + } + + /** + * @tests java.lang.ThreadGroup#uncaughtException(java.lang.Thread, + * java.lang.Throwable) + */ + public void test_uncaughtExceptionLjava_lang_ThreadLjava_lang_Throwable() { + // Test for method void + // java.lang.ThreadGroup.uncaughtException(java.lang.Thread, + // java.lang.Throwable) + + final ThreadGroup originalCurrent = getInitialThreadGroup(); + + // indices for the array defined below + final int TEST_DEATH = 0; + final int TEST_OTHER = 1; + final int TEST_EXCEPTION_IN_UNCAUGHT = 2; + final int TEST_OTHER_THEN_DEATH = 3; + final int TEST_FORCING_THROW_THREAD_DEATH = 4; + final int TEST_KILLING = 5; + final int TEST_DEATH_AFTER_UNCAUGHT = 6; + + final boolean[] passed = new boolean[] { false, false, false, false, + false, false, false }; + + ThreadGroup testRoot; + Thread thread; + + // Our own exception class + class TestException extends RuntimeException { + } + ; + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // - - - - - - - + testRoot = new ThreadGroup(originalCurrent, + "Test killing a Thread, forcing it to throw ThreadDeath") { + public void uncaughtException(Thread t, Throwable e) { + if (e instanceof ThreadDeath) + passed[TEST_KILLING] = true; + // always forward, any exception + super.uncaughtException(t, e); + } + }; + + // Test if a Thread tells its ThreadGroup about ThreadDeath + thread = new Thread(testRoot, null, "victim thread (to be killed)") { + public void run() { + while (true) { + Thread.yield(); + } + } + }; + thread.start(); + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + fail("Should not have been interrupted"); + } + // we know this is deprecated, but we must test this scenario. + // When we stop a thread, it is tagged as not alive even though it is + // still running code. + // join would be a no-op, and we might have a race condition. So, to + // play safe, we wait before joining & testing if the exception was + // really forwarded to the ThreadGroup + thread.stop(); + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + fail("Should not have been interrupted"); + } + try { + thread.join(); + } catch (InterruptedException ie) { + fail("Should not have been interrupted"); + } + testRoot.destroy(); + assertTrue( + "Any thread should notify its ThreadGroup about its own death, even if killed:" + + testRoot, passed[TEST_KILLING]); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // - - - - - - - + testRoot = new ThreadGroup(originalCurrent, + "Test Forcing a throw of ThreadDeath") { + public void uncaughtException(Thread t, Throwable e) { + if (e instanceof ThreadDeath) + passed[TEST_FORCING_THROW_THREAD_DEATH] = true; + // always forward, any exception + super.uncaughtException(t, e); + } + }; + + // Test if a Thread tells its ThreadGroup about ThreadDeath + thread = new Thread(testRoot, null, "suicidal thread") { + public void run() { + throw new ThreadDeath(); + } + }; + thread.start(); + try { + thread.join(); + } catch (InterruptedException ie) { + fail("Should not have been interrupted"); + } + testRoot.destroy(); + assertTrue( + "Any thread should notify its ThreadGroup about its own death, even if suicide:" + + testRoot, passed[TEST_FORCING_THROW_THREAD_DEATH]); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // - - - - - - - + + testRoot = new ThreadGroup(originalCurrent, "Test ThreadDeath") { + public void uncaughtException(Thread t, Throwable e) { + passed[TEST_DEATH] = false; + // always forward, any exception + super.uncaughtException(t, e); + } + }; + + // Test if a Thread tells its ThreadGroup about ThreadDeath + passed[TEST_DEATH] = true; + thread = new Thread(testRoot, null, "no-op thread"); + thread.start(); + try { + thread.join(); + } catch (InterruptedException ie) { + fail("Should not have been interrupted"); + } + testRoot.destroy(); + assertTrue("A thread should not call uncaughtException when it dies:" + + testRoot, passed[TEST_DEATH]); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // - - - - - - - + + testRoot = new ThreadGroup(originalCurrent, "Test other Exception") { + public void uncaughtException(Thread t, Throwable e) { + if (e instanceof TestException) + passed[TEST_OTHER] = true; + else + // only forward exceptions other than our test + super.uncaughtException(t, e); + } + }; + + // Test if a Thread tells its ThreadGroup about an Exception + thread = new Thread(testRoot, null, "no-op thread") { + public void run() { + throw new TestException(); + } + }; + thread.start(); + try { + thread.join(); + } catch (InterruptedException ie) { + fail("Should not have been interrupted"); + } + testRoot.destroy(); + assertTrue( + "Any thread should notify its ThreadGroup about an uncaught exception:" + + testRoot, passed[TEST_OTHER]); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // - - - - - - - + + // Our own uncaught exception class + class UncaughtException extends TestException { + } + ; + + testRoot = new ThreadGroup(originalCurrent, + "Test Exception in uncaught exception") { + public void uncaughtException(Thread t, Throwable e) { + if (e instanceof TestException) { + passed[TEST_EXCEPTION_IN_UNCAUGHT] = true; + // Let's simulate an error inside our uncaughtException + // method. + // This should be no-op according to the spec + throw new UncaughtException(); + } else + // only forward exceptions other than our test + super.uncaughtException(t, e); + } + }; + + // Test if an Exception in uncaughtException is really a no-op + thread = new Thread(testRoot, null, "no-op thread") { + public void run() { + try { + throw new TestException(); + } catch (UncaughtException ue) { + // any exception in my ThreadGroup's uncaughtException must + // not be propagated. + // If it gets propagated and we detected that, the test failed + passed[TEST_EXCEPTION_IN_UNCAUGHT] = false; + } + } + }; + thread.start(); + try { + thread.join(); + } catch (InterruptedException ie) { + fail("Should not have been interrupted"); + } + testRoot.destroy(); + assertTrue( + "Any uncaughtException in uncaughtException should be no-op:" + + testRoot, passed[TEST_EXCEPTION_IN_UNCAUGHT]); + + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + // - - - - - - - + + // This is a mix of 2 of the tests above. It is assumed that ThreadDeath + // and any random exception do work , tested separately. Now we test + // if after an uncaughtException is forwarded to the ThreadGroup and + // the Thread dies, if ThreadDeath is also forwarded. It should be + // (so that a ThreadGroup can know its Thread died) + testRoot = new ThreadGroup(originalCurrent, + "Test Uncaught followed by ThreadDeath") { + public void uncaughtException(Thread t, Throwable e) { + if (e instanceof ThreadDeath) + passed[TEST_DEATH_AFTER_UNCAUGHT] = true; + if (e instanceof TestException) + passed[TEST_OTHER_THEN_DEATH] = true; + else + // only forward exceptions other than our test + super.uncaughtException(t, e); + } + }; + + // Test if a Thread tells its ThreadGroup about an Exception and also + // ThreadDeath + thread = new Thread(testRoot, null, "no-op thread") { + public void run() { + throw new TestException(); + } + }; + thread.start(); + try { + thread.join(); + } catch (InterruptedException ie) { + fail("Should not have been interrupted"); + } + testRoot.destroy(); + } + + /** + * Sets up the fixture, for example, open a network connection. This method + * is called before a test is executed. + */ + protected void setUp() { + initialThreadGroup = Thread.currentThread().getThreadGroup(); + rootThreadGroup = initialThreadGroup; + while (rootThreadGroup.getParent() != null) + rootThreadGroup = rootThreadGroup.getParent(); + } + + /** + * Tears down the fixture, for example, close a network connection. This + * method is called after a test is executed. + */ + protected void tearDown() { + try { + // Give the threads a chance to die. + Thread.sleep(50); + } catch (InterruptedException e) { + } + } + + private Thread[] threads(ThreadGroup parent) { + // No API to get the count of immediate children only ? + int count = parent.activeCount(); + Thread[] all = new Thread[count]; + int actualSize = parent.enumerate(all, false); + Thread[] result; + if (actualSize == all.length) + result = all; + else { + result = new Thread[actualSize]; + System.arraycopy(all, 0, result, 0, actualSize); + } + + return result; + + } + + private ThreadGroup getInitialThreadGroup() { + return initialThreadGroup; + } + + private ThreadGroup[] allGroups(ThreadGroup parent) { + int count = parent.activeGroupCount(); + ThreadGroup[] all = new ThreadGroup[count]; + parent.enumerate(all, true); + return all; + } + + private void daemonTests() { + // Test for method void java.lang.ThreadGroup.setDaemon(boolean) + + final ThreadGroup originalCurrent = getInitialThreadGroup(); + final ThreadGroup testRoot = new ThreadGroup(originalCurrent, + "Test group"); + + testRoot.setDaemon(true); + assertTrue("Setting daemon&getting does not work", testRoot.isDaemon()); + + testRoot.setDaemon(false); + assertTrue("Setting daemon&getting does not work", !testRoot.isDaemon()); + + testRoot.destroy(); + + } + + private boolean wipeAllThreads(final ThreadGroup aGroup) { + boolean ok = true; + Thread[] threads = threads(aGroup); + for (int i = 0; i < threads.length; i++) { + Thread t = threads[i]; + ok = ok && wipeThread(t); + } + + // Recursively for subgroups (if any) + ThreadGroup[] children = groups(aGroup); + for (int i = 0; i < children.length; i++) { + ok = ok && wipeAllThreads(children[i]); + } + + return ok; + + } + + private boolean wipeAllThreads(final Vector threads) { + boolean ok = true; + for (int i = 0; i < threads.size(); i++) { + Thread t = (Thread) threads.elementAt(i); + ok = ok && wipeThread(t); + } + + return ok; + + } + + private boolean wipeSideEffectThreads(ThreadGroup aGroup) { + boolean ok = true; + Thread[] threads = threads(aGroup); + for (int i = 0; i < threads.length; i++) { + Thread t = threads[i]; + if (t.getName().equals("SimpleThread") + || t.getName().equals("Bogus Name") + || t.getName().equals("Testing") + || t.getName().equals("foo") + || t.getName().equals("Test Group") + || t.getName().equals("Squawk") + || t.getName().equals("Thread-1") + || t.getName().equals("firstOne") + || t.getName().equals("secondOne") + || t.getName().equals("Thread-16") + || t.getName().equals("Thread-14")) + ok = ok && wipeThread(t); + } + + // Recursively for subgroups (if any) + ThreadGroup[] children = groups(aGroup); + + for (int i = 0; i < children.length; i++) { + ok = ok && wipeSideEffectThreads(children[i]); + if (children[i].getName().equals("Test Group") + || children[i].getName().equals("foo") + || children[i].getName().equals("jp")) + children[i].destroy(); + } + try { + // Give the threads a chance to die. + Thread.sleep(50); + } catch (InterruptedException e) { + } + return ok; + } + + private void asyncBuildRandomTreeUnder(final ThreadGroup aGroup, + final int depth, final Vector allCreated) { + if (depth <= 0) + return; + + final int maxImmediateSubgroups = random(3); + for (int i = 0; i < maxImmediateSubgroups; i++) { + final int iClone = i; + final String name = " Depth = " + depth + ",N = " + iClone + + ",Vector size at creation: " + allCreated.size(); + // Use concurrency to maximize chance of exposing concurrency bugs + // in ThreadGroups + Thread t = new Thread(aGroup, name) { + public void run() { + ThreadGroup newGroup = new ThreadGroup(aGroup, name); + allCreated.addElement(newGroup); + asyncBuildRandomTreeUnder(newGroup, depth - 1, allCreated); + } + }; + t.start(); + } + + } + + private Vector asyncBuildRandomTreeUnder(final ThreadGroup aGroup, + final int depth) { + Vector result = new Vector(); + asyncBuildRandomTreeUnder(aGroup, depth, result); + return result; + + } + + private boolean verifyThreadList(ThreadGroup root, + ThreadGroup onlyChildGroup, byte[] listOutput) { + // We expect that @root has only 1 subgroup, @onlyChildGroup. The + // output from method 'list' is stored in @listOutput + if (listOutput.length == 0) { + return false; + } + + // If we got a long output, it means some previous test must have left + // side-effects (more subgroups and threads); + final int MAX_SIZE = 200; + if (listOutput.length > MAX_SIZE) { + return false; + } + + // Here we compare actual result to expected result + + // Due to extremely weak API in String, comparing substrings, etc would + // take too much work at this time. + // We defer the actual implementation for now. + return true; + } + + private boolean allNotSuspended(Vector threads) { + for (int i = 0; i < threads.size(); i++) { + MyThread t = (MyThread) threads.elementAt(i); + if (!t.isActivelyRunning()) + return false; + } + + return true; + + } + + private boolean allSuspended(Vector threads) { + for (int i = 0; i < threads.size(); i++) { + MyThread t = (MyThread) threads.elementAt(i); + if (t.isActivelyRunning()) + return false; + } + + return true; + + } + + private boolean sameThreads(Thread[] allThreads, Vector threads) { + if (allThreads.length != threads.size()) + return false; + + // The complexity of this method is N2, and we do it twice !! + + // First make sure that all threads in @threads are also in @allThreads + for (int i = 0; i < allThreads.length; i++) { + Thread t = (Thread) threads.elementAt(i); + if (!arrayIncludes(allThreads, t)) + return false; + } + + // Now make sure that all threads in @allThreads are also in @threads + Thread[] vectorThreads = new Thread[threads.size()]; + threads.copyInto(vectorThreads); + for (int i = 0; i < vectorThreads.length; i++) { + Thread t = allThreads[i]; + if (!arrayIncludes(vectorThreads, t)) + return false; + } + + return true; + + } + + private ThreadGroup[] groups(ThreadGroup parent) { + // No API to get the count of immediate children only ? + int count = parent.activeGroupCount(); + ThreadGroup[] all = new ThreadGroup[count]; + parent.enumerate(all, false); + // Now we may have nulls in the array, we must find the actual size + int actualSize = 0; + for (; actualSize < all.length; actualSize++) { + if (all[actualSize] == null) + break; + } + ThreadGroup[] result; + if (actualSize == all.length) + result = all; + else { + result = new ThreadGroup[actualSize]; + System.arraycopy(all, 0, result, 0, actualSize); + } + + return result; + + } + + private Vector populateGroupsWithThreads(final ThreadGroup aGroup, + final int threadCount) { + Vector result = new Vector(); + populateGroupsWithThreads(aGroup, threadCount, result); + return result; + + } + + private void populateGroupsWithThreads(final ThreadGroup aGroup, + final int threadCount, final Vector allCreated) { + for (int i = 0; i < threadCount; i++) { + final int iClone = i; + final String name = "(MyThread)N =" + iClone + "/" + threadCount + + " ,Vector size at creation: " + allCreated.size(); + + MyThread t = new MyThread(aGroup, name); + allCreated.addElement(t); + } + + // Recursively for subgroups (if any) + ThreadGroup[] children = groups(aGroup); + for (int i = 0; i < children.length; i++) { + populateGroupsWithThreads(children[i], threadCount, allCreated); + } + + } + + private int random(int max) { + + return 1 + ((new Object()).hashCode() % max); + + } + + private boolean parentOfAll(ThreadGroup parentCandidate, + ThreadGroup[] childrenCandidates) { + for (int i = 0; i < childrenCandidates.length; i++) { + if (!parentCandidate.parentOf(childrenCandidates[i])) + return false; + } + + return true; + + } + + private boolean wipeThread(Thread t) { + t.stop(); + try { + t.join(1000); + } catch (InterruptedException ie) { + fail("Should not have been interrupted"); + } + // The thread had plenty (subjective) of time to die so there + // is a problem. + if (t.isAlive()) + return false; + + return true; + } + + private Vector buildRandomTreeUnder(ThreadGroup aGroup, int depth) { + Vector result = asyncBuildRandomTreeUnder(aGroup, depth); + while (true) { + int sizeBefore = result.size(); + try { + Thread.sleep(1000); + int sizeAfter = result.size(); + // If no activity for a while, we assume async building may be + // done. + if (sizeBefore == sizeAfter) + // It can only be done if no more threads. Unfortunately we + // are relying on this API to work as well. + // If it does not, we may loop forever. + if (aGroup.activeCount() == 0) + break; + } catch (InterruptedException e) { + } + } + return result; + + } + + private boolean arrayIncludes(Object[] array, Object toTest) { + for (int i = 0; i < array.length; i++) { + if (array[i] == toTest) + return true; + } + + return false; + } + + protected void myassertTrue(String msg, boolean b) { + // This method is defined here just to solve a visibility problem + // of protected methods with inner types + this.assertTrue(msg, b); + } + + private ThreadGroup getRootThreadGroup() { + return rootThreadGroup; + + } +} Added: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/ThreadLocalTest.java URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/ThreadLocalTest.java?rev=386058&view=auto ============================================================================== --- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/ThreadLocalTest.java (added) +++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/test/java/tests/api/java/lang/ThreadLocalTest.java Wed Mar 15 03:46:17 2006 @@ -0,0 +1,133 @@ +/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tests.api.java.lang; + +public class ThreadLocalTest extends junit.framework.TestCase { + + /** + * @tests java.lang.ThreadLocal#ThreadLocal() + */ + public void test_Constructor() { + // Test for method java.lang.ThreadLocal() + + ThreadLocal l = new ThreadLocal(); + assertTrue("Failed to create ThreadLocal", l instanceof ThreadLocal); + + } + + /** + * @tests java.lang.ThreadLocal#get() + */ + public void test_get() { + // Test for method java.lang.Object java.lang.ThreadLocal.get() + ThreadLocal l = new ThreadLocal(); + assertTrue("ThreadLocal's initial value is null", l.get() == null); + + // The ThreadLocal has to run once for each thread that touches the + // ThreadLocal + final Object INITIAL_VALUE = "'foo'"; + final ThreadLocal l1 = new ThreadLocal() { + protected Object initialValue() { + return INITIAL_VALUE; + } + }; + + assertTrue("ThreadLocal's initial value should be " + INITIAL_VALUE + + " but is " + l1.get(), l1.get() == INITIAL_VALUE); + + // We need this because inner types cannot assign to variables in + // container method. But assigning to object slots in the container + // method is ok. + class ResultSlot { + public Object result = null; + } + + final ResultSlot THREADVALUE = new ResultSlot(); + Thread t = new Thread() { + public void run() { + THREADVALUE.result = l1.get(); + } + }; + + // Wait for the other Thread assign what it observes as the value of the + // variable + t.start(); + try { + t.join(); + } catch (InterruptedException ie) { + fail("Interrupted!!"); + } + + assertTrue("ThreadLocal's initial value in other Thread should be " + + INITIAL_VALUE, THREADVALUE.result == INITIAL_VALUE); + + } + + /** + * @tests java.lang.ThreadLocal#set(java.lang.Object) + */ + public void test_setLjava_lang_Object() { + // Test for method void java.lang.ThreadLocal.set(java.lang.Object) + + final Object OBJ = new Object(); + final ThreadLocal l = new ThreadLocal(); + l.set(OBJ); + assertTrue("ThreadLocal's initial value is " + OBJ, l.get() == OBJ); + + // We need this because inner types cannot assign to variables in + // container method. + // But assigning to object slots in the container method is ok. + class ResultSlot { + public Object result = null; + } + + final ResultSlot THREADVALUE = new ResultSlot(); + Thread t = new Thread() { + public void run() { + THREADVALUE.result = l.get(); + } + }; + + // Wait for the other Thread assign what it observes as the value of the + // variable + t.start(); + try { + t.join(); + } catch (InterruptedException ie) { + fail("Interrupted!!"); + } + + // ThreadLocal is not inherited, so the other Thread should see it as + // null + assertTrue("ThreadLocal's value in other Thread should be null", + THREADVALUE.result == null); + + } + + /** + * Sets up the fixture, for example, open a network connection. This method + * is called before a test is executed. + */ + protected void setUp() { + } + + /** + * Tears down the fixture, for example, close a network connection. This + * method is called after a test is executed. + */ + protected void tearDown() { + } +}