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