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 
18 package libcore.java.lang;
19 
20 import java.io.ByteArrayOutputStream;
21 import java.io.PrintStream;
22 import java.util.concurrent.Semaphore;
23 import java.util.concurrent.locks.LockSupport;
24 import libcore.java.lang.ref.FinalizationTester;
25 
26 public class OldThreadTest extends junit.framework.TestCase {
27 
28     static class SimpleThread implements Runnable {
29         int delay;
30 
run()31         public void run() {
32             try {
33                 synchronized (this) {
34                     this.notify();
35                     this.wait(delay);
36                 }
37             } catch (InterruptedException e) {
38                 return;
39             }
40 
41         }
42 
SimpleThread(int d)43         public SimpleThread(int d) {
44             if (d >= 0)
45                 delay = d;
46         }
47     }
48 
49     @SuppressWarnings("DeadThread")
test_ConstructorLjava_lang_ThreadGroupLjava_lang_RunnableLjava_lang_StringL$L()50     public void test_ConstructorLjava_lang_ThreadGroupLjava_lang_RunnableLjava_lang_StringL$L() {
51         ThreadGroup tg = new ThreadGroup("Test Group2");
52         st = new Thread(tg, new SimpleThread(1), "SimpleThread3", 1);
53         assertTrue("Constructed incorrect thread", (st.getThreadGroup() == tg)
54                 && st.getName().equals("SimpleThread3"));
55         st.start();
56         try {
57             st.join();
58         } catch (InterruptedException e) {
59         }
60         tg.destroy();
61 
62         try {
63             new Thread(tg, new SimpleThread(1), "SimpleThread3",
64                     Integer.MAX_VALUE);
65             fail("StackOverflowError/OutOfMemoryError is not thrown.");
66         } catch(IllegalThreadStateException itse) {
67             //expected
68         }
69 
70     }
71 
test_dumpStack()72     public void test_dumpStack() {
73         try {
74             PrintStream savedErr = System.err;
75             ByteArrayOutputStream baos = new ByteArrayOutputStream();
76             System.setErr(new PrintStream(baos));
77             Thread.dumpStack();
78             System.setErr(savedErr);
79 
80             String s = new String(baos.toByteArray());
81 
82             assertTrue(s.contains("java.lang.Thread.dumpStack"));
83 
84         } catch(Exception e) {
85             fail("Unexpected exception was thrown: " + e.toString());
86         }
87     }
88 
89     class MonitoredClass {
enterLocked()90         public synchronized void enterLocked() {
91             boolean b = Thread.holdsLock(this);
92             assertTrue("Thread should hold lock for object", b);
93         }
94 
enterNonLocked()95         public void enterNonLocked() {
96             boolean b = Thread.holdsLock(this);
97             assertFalse("Thread should not hold lock for object", b);
98         }
99 
100     }
101 
102     boolean wasInterrupted = false;
103 
test_joinWithSpuriousInterruption()104     public void test_joinWithSpuriousInterruption() throws InterruptedException {
105         final Thread parker = new Thread() {
106             @Override
107             public void run() {
108                 for (int i = 0; i < 10; i++) {
109                     // we used to get spurious wakeups upon unparking
110                     LockSupport.park();
111                 }
112             }
113         };
114         Thread unparker = new Thread() {
115             @Override
116             public void run() {
117                 for (int i = 0; i < 10; i++) {
118                     try {
119                         Thread.sleep(100);
120                         LockSupport.unpark(parker);
121                     } catch (InterruptedException expected) {
122                     }
123                 }
124             }
125         };
126 
127         long startNanos = System.nanoTime();
128         parker.start();
129         unparker.start();
130         parker.join(500, 500000);
131         long netWaitTime = System.nanoTime() - startNanos;
132         assertTrue("Expected to wait at least 500000000ns, but was " + netWaitTime + "ns",
133                 netWaitTime > 500000000);
134     }
135 
test_setContextClassLoader()136     public void test_setContextClassLoader() {
137         ClassLoader pcl = new ClassLoader() {};
138         st = new Thread();
139         st.setContextClassLoader(pcl);
140         assertEquals(pcl, st.getContextClassLoader());
141 
142         st.setContextClassLoader(null);
143         assertNull(st.getContextClassLoader());
144     }
145 
test_setDaemonZ()146     public void test_setDaemonZ() {
147         st = new Thread(new SimpleThread(5));
148         st.start();
149         try {
150             st.setDaemon(false);
151             fail("setDaemon() must throw exception for started thread");
152         } catch (IllegalThreadStateException ex) {
153             // We expect this one.
154         }
155     }
156 
launchFiveSecondFakeThread()157     private Thread launchFiveSecondFakeThread() {
158         Thread thread = new Thread() {
159             public void run() {
160                 try {
161                     Thread.sleep(5000);
162                 } catch (InterruptedException e) {
163                     // Ignore
164                 }
165             }
166         };
167 
168         thread.start();
169 
170         return thread;
171     }
172 
173     /**
174      * java.lang.Thread#sleep(long)
175      */
test_sleepJ()176     public void test_sleepJ() {
177         // Note: Not too much we can test here that can be reliably measured.
178 
179         // Check that basic behavior is about right (with some tolerance)
180         long stime = System.currentTimeMillis();
181 
182         try {
183             Thread.sleep(1000);
184         } catch (InterruptedException e) {
185             fail("Unexpected InterruptedException was thrown");
186         }
187 
188         long ftime = System.currentTimeMillis();
189 
190         assertTrue("Failed to sleep long enough", (ftime - stime) >= 500);
191         assertTrue("Failed to wake up early enough", (ftime - stime) <= 1500);
192 
193         // Check that interrupt works
194         st = new Thread() {
195             public void run() {
196                 try {
197                     sleep(1000);
198                 } catch(InterruptedException ie) {
199                     wasInterrupted = true;
200                 }
201             }
202         };
203 
204         st.start();
205 
206         try {
207             Thread.sleep(500);
208         } catch(InterruptedException e) {
209             fail("Unexpected InterruptedException was thrown");
210         }
211 
212         st.interrupt();
213 
214         try {
215             Thread.sleep(500);
216         } catch(InterruptedException e) {
217             fail("Unexpected InterruptedException was thrown");
218         }
219 
220         assertTrue(wasInterrupted);
221     }
222 
test_sleepJI()223     public void test_sleepJI() {
224         // Note: Not too much we can test here that can be reliably measured.
225 
226         // Check that basic behavior is about right (with some tolerance)
227         long stime = System.currentTimeMillis();
228 
229         try {
230             Thread.sleep(1000, 99999);
231         } catch (InterruptedException e) {
232             fail("Unexpected InterruptedException was thrown");
233         }
234 
235         long ftime = System.currentTimeMillis();
236 
237         assertTrue("Failed to sleep long enough", (ftime - stime) >= 500);
238         assertTrue("Failed to wake up early enough", (ftime - stime) <= 1500);
239 
240         // Check that interrupt works
241         st = new Thread() {
242             public void run() {
243                 try {
244                     sleep(1000, 9999);
245                 } catch(InterruptedException ie) {
246                     wasInterrupted = true;
247                 }
248             }
249         };
250 
251         st.start();
252 
253         try {
254             Thread.sleep(500, 9999);
255         } catch(InterruptedException e) {
256             fail("Unexpected InterruptedException was thrown");
257         }
258 
259         st.interrupt();
260 
261         try {
262             Thread.sleep(500);
263         } catch(InterruptedException e) {
264             fail("Unexpected InterruptedException was thrown");
265         }
266 
267         assertTrue(wasInterrupted);
268     }
269 
test_yield()270     public void test_yield() {
271 
272         Counter [] countersNotYeld = new Counter[10];
273 
274         for(int i = 0; i < 10; i++) {
275             countersNotYeld[i] = new Counter(false);
276         }
277         Counter countersYeld = new Counter(true);
278         try {
279             Thread.sleep(1100);
280         } catch(InterruptedException ie) {}
281 
282         for(Counter c:countersNotYeld) {
283             assertTrue(countersYeld.counter == c.counter);
284         }
285     }
286 
287     class Counter extends Thread {
288         public int counter = 0;
289         boolean isDoYield = false;
290 
Counter(boolean isDoYield)291         public Counter(boolean isDoYield) {
292             this.isDoYield = isDoYield;
293             start();
294         }
295 
run()296         public void run() {
297             for(int i = 0; i < 1000; i++) {
298                 if(isDoYield)
299                     yield();
300                 counter ++;
301             }
302         }
303     }
304 
305 
test_getState()306     public void test_getState() throws InterruptedException {
307         Thread.State state = Thread.currentThread().getState();
308         assertNotNull(state);
309         assertEquals(Thread.State.RUNNABLE, state);
310 
311         run = true;
312         final Semaphore sem = new Semaphore(0);
313         final Object lock = new Object();
314         Thread th = new Thread() {
315             @Override
316             public void run() {
317                   while (!sem.hasQueuedThreads()) {}
318                   sem.release();
319 
320                   // RUNNABLE
321                   while (run) {}
322 
323                   try {
324                       // WAITING
325                       sem.acquire();
326                   } catch (InterruptedException e) {
327                       fail("InterruptedException was thrown.");
328                   }
329 
330                   // BLOCKED
331                   synchronized (lock) {
332                       lock.equals(new Object());
333                   }
334                   synchronized (lock) {
335                       try {
336                         sem.release();
337 
338                         // TIMED_WAITING
339                         lock.wait(Long.MAX_VALUE);
340                       } catch (InterruptedException e) {
341                           // expected
342                       }
343                   }
344 
345                   // TERMINATED upon return
346             }
347         };
348         assertEquals(Thread.State.NEW, th.getState());
349         th.start();
350         sem.acquire();
351         assertEquals(Thread.State.RUNNABLE, th.getState());
352         run = false;
353 
354         Thread.sleep(200);
355 
356         assertEquals(Thread.State.WAITING, th.getState());
357         synchronized (lock) {
358             sem.release();
359             long start = System.currentTimeMillis();
360             while(start + 1000 > System.currentTimeMillis()) {}
361             assertEquals(Thread.State.BLOCKED, th.getState());
362         }
363 
364         sem.acquire();
365 
366         synchronized (lock) {
367             assertEquals(Thread.State.TIMED_WAITING, th.getState());
368             th.interrupt();
369         }
370 
371         th.join(1000);
372         assertEquals(Thread.State.TERMINATED, th.getState());
373     }
374     volatile boolean run;
375 
test_holdsLock()376     public void test_holdsLock() {
377         MonitoredClass monitor = new MonitoredClass();
378 
379         monitor.enterLocked();
380         monitor.enterNonLocked();
381 
382         try {
383             Thread.holdsLock(null);
384             fail("NullPointerException was not thrown.");
385         } catch(NullPointerException npe) {
386             //expected
387         }
388     }
389 
390     @SuppressWarnings("deprecation")
test_stop()391     public void test_stop() {
392         Thread thread = launchFiveSecondFakeThread();
393 
394         try {
395             Thread.sleep(1000);
396         } catch (InterruptedException e) {
397             // Ignore
398         }
399 
400         try {
401             thread.stop();
402             fail();
403         } catch (UnsupportedOperationException expected) {
404         }
405     }
406 
test_start()407     public void test_start() {
408         Thread thr = new Thread();
409         thr.start();
410         try {
411             thr.start();
412         } catch(IllegalThreadStateException itse){
413             //expected
414         }
415     }
416 
417     @SuppressWarnings("deprecation")
test_stopLjava_lang_Throwable_subtest0()418     public void test_stopLjava_lang_Throwable_subtest0() {
419         Thread thread = new Thread() {
420             public void run() {
421                 try {
422                     Thread.sleep(5000);
423                 } catch (InterruptedException e) {
424                     // Ignore
425                 }
426             }
427         };
428 
429         thread.start();
430         try {
431             Thread.sleep(1000);
432         } catch (InterruptedException e) {
433             // Ignore
434         }
435 
436         try {
437             thread.stop(new Exception("Oops!"));
438             fail();
439         } catch (UnsupportedOperationException expected) {
440         }
441     }
442 
443     @SuppressWarnings("deprecation")
test_suspend()444     public void test_suspend() {
445         Thread thread = launchFiveSecondFakeThread();
446 
447         try {
448             Thread.sleep(1000);
449         } catch (InterruptedException e) {
450             // Ignore
451         }
452 
453         try {
454             thread.suspend();
455             fail();
456         } catch (UnsupportedOperationException expected) {
457         }
458     }
459 
460     Thread st, ct, spinner;
461 
462     @Override
tearDown()463     protected void tearDown() {
464         try {
465             if (st != null)
466                 st.interrupt();
467         } catch (Exception e) {
468         }
469         try {
470             if (spinner != null)
471                 spinner.interrupt();
472         } catch (Exception e) {
473         }
474         try {
475             if (ct != null)
476                 ct.interrupt();
477         } catch (Exception e) {
478         }
479 
480         try {
481             spinner = null;
482             st = null;
483             ct = null;
484             FinalizationTester.induceFinalization();
485         } catch (Exception e) {
486         }
487     }
488 }
489