1/* 2 * Copyright (C) 2010 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.lang; 18 19import java.util.concurrent.atomic.AtomicInteger; 20import junit.framework.Assert; 21import junit.framework.TestCase; 22import libcore.java.lang.ref.FinalizationTester; 23 24public final class ThreadTest extends TestCase { 25 static { 26 System.loadLibrary("javacoretests"); 27 } 28 29 /** 30 * getContextClassLoader returned a non-application class loader. 31 * http://code.google.com/p/android/issues/detail?id=5697 32 */ 33 public void testJavaContextClassLoader() throws Exception { 34 Assert.assertNotNull("Must have a Java context ClassLoader", 35 Thread.currentThread().getContextClassLoader()); 36 } 37 38 public void testLeakingStartedThreads() { 39 final AtomicInteger finalizedThreadsCount = new AtomicInteger(); 40 for (int i = 0; true; i++) { 41 try { 42 newThread(finalizedThreadsCount, 1024 << i).start(); 43 } catch (OutOfMemoryError expected) { 44 break; 45 } 46 } 47 FinalizationTester.induceFinalization(); 48 assertTrue("Started threads were never finalized!", finalizedThreadsCount.get() > 0); 49 } 50 51 public void testLeakingUnstartedThreads() { 52 final AtomicInteger finalizedThreadsCount = new AtomicInteger(); 53 for (int i = 0; true; i++) { 54 try { 55 newThread(finalizedThreadsCount, 1024 << i); 56 } catch (OutOfMemoryError expected) { 57 break; 58 } 59 } 60 FinalizationTester.induceFinalization(); 61 assertTrue("Unstarted threads were never finalized!", finalizedThreadsCount.get() > 0); 62 } 63 64 public void testThreadSleep() throws Exception { 65 int millis = 1000; 66 long start = System.currentTimeMillis(); 67 68 Thread.sleep(millis); 69 70 long elapsed = System.currentTimeMillis() - start; 71 long offBy = Math.abs(elapsed - millis); 72 73 assertTrue("Actual sleep off by " + offBy + " ms", offBy <= 250); 74 } 75 76 public void testThreadInterrupted() throws Exception { 77 Thread.currentThread().interrupt(); 78 try { 79 Thread.sleep(0); 80 fail(); 81 } catch (InterruptedException e) { 82 assertFalse(Thread.currentThread().isInterrupted()); 83 } 84 } 85 86 public void testThreadSleepIllegalArguments() throws Exception { 87 88 try { 89 Thread.sleep(-1); 90 fail(); 91 } catch (IllegalArgumentException expected) { 92 } 93 94 try { 95 Thread.sleep(0, -1); 96 fail(); 97 } catch (IllegalArgumentException expected) { 98 } 99 100 try { 101 Thread.sleep(0, 1000000); 102 fail(); 103 } catch (IllegalArgumentException expected) { 104 } 105 } 106 107 public void testThreadWakeup() throws Exception { 108 WakeupTestThread t1 = new WakeupTestThread(); 109 WakeupTestThread t2 = new WakeupTestThread(); 110 111 t1.start(); 112 t2.start(); 113 assertTrue("Threads already finished", !t1.done && !t2.done); 114 115 t1.interrupt(); 116 t2.interrupt(); 117 118 Thread.sleep(1000); 119 assertTrue("Threads did not finish", t1.done && t2.done); 120 } 121 122 public void testContextClassLoaderIsNotNull() { 123 assertNotNull(Thread.currentThread().getContextClassLoader()); 124 } 125 126 public void testContextClassLoaderIsInherited() { 127 Thread other = new Thread(); 128 assertSame(Thread.currentThread().getContextClassLoader(), other.getContextClassLoader()); 129 } 130 131 /** 132 * Thread.getStackTrace() is broken. http://b/1252043 133 */ 134 public void testGetStackTrace() throws Exception { 135 Thread t1 = new Thread("t1") { 136 @Override public void run() { 137 doSomething(); 138 } 139 public void doSomething() { 140 for (int i = 0; i < 20;) { 141 try { 142 Thread.sleep(100); 143 } catch (InterruptedException ignored) { 144 } 145 } 146 } 147 }; 148 t1.start(); 149 Thread.sleep(1000); 150 StackTraceElement[] traces = t1.getStackTrace(); 151 StackTraceElement trace = traces[traces.length - 2]; 152 153 // Expect to find MyThread.doSomething in the trace 154 assertTrue(trace.getClassName().contains("ThreadTest") 155 && trace.getMethodName().equals("doSomething")); 156 } 157 158 public void testGetAllStackTracesIncludesAllGroups() throws Exception { 159 final AtomicInteger visibleTraces = new AtomicInteger(); 160 ThreadGroup group = new ThreadGroup("1"); 161 Thread t2 = new Thread(group, "t2") { 162 @Override public void run() { 163 visibleTraces.set(Thread.getAllStackTraces().size()); 164 } 165 }; 166 t2.start(); 167 t2.join(); 168 169 // Expect to see the traces of all threads (not just t2) 170 assertTrue("Must have traces for all threads", visibleTraces.get() > 1); 171 } 172 173 // http://b/27748318 174 public void testNativeThreadNames() throws Exception { 175 String testResult = nativeTestNativeThreadNames(); 176 // Not using assertNull here because this results in a better error message. 177 if (testResult != null) { 178 fail(testResult); 179 } 180 } 181 182 // This method returns {@code null} if all tests pass, or a non-null String containing 183 // failure details if an error occured. 184 private static native String nativeTestNativeThreadNames(); 185 186 private Thread newThread(final AtomicInteger finalizedThreadsCount, final int size) { 187 return new Thread() { 188 long[] memoryPressure = new long[size]; 189 @Override protected void finalize() throws Throwable { 190 super.finalize(); 191 finalizedThreadsCount.incrementAndGet(); 192 } 193 }; 194 } 195 196 private class WakeupTestThread extends Thread { 197 public boolean done; 198 199 public void run() { 200 done = false; 201 202 // Sleep for a while (1 min) 203 try { 204 Thread.sleep(60000); 205 } catch (InterruptedException ignored) { 206 } 207 208 done = true; 209 } 210 } 211} 212