1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.luni.tests.java.lang;
19
20import java.lang.Thread.UncaughtExceptionHandler;
21import java.security.Permission;
22import java.util.Map;
23
24public class ThreadTest extends junit.framework.TestCase {
25
26	static class SimpleThread implements Runnable {
27		int delay;
28
29		public void run() {
30			try {
31				synchronized (this) {
32					this.notify();
33					this.wait(delay);
34				}
35			} catch (InterruptedException e) {
36				return;
37			}
38
39		}
40
41		public SimpleThread(int d) {
42			if (d >= 0)
43				delay = d;
44		}
45	}
46
47	static class YieldThread implements Runnable {
48		volatile int delay;
49
50		public void run() {
51			int x = 0;
52			while (true) {
53				++x;
54			}
55		}
56
57		public YieldThread(int d) {
58			if (d >= 0)
59				delay = d;
60		}
61	}
62
63	static class ResSupThread implements Runnable {
64		Thread parent;
65
66		volatile int checkVal = -1;
67
68		public void run() {
69			try {
70				synchronized (this) {
71					this.notify();
72				}
73				while (true) {
74					checkVal++;
75					zz();
76					Thread.sleep(100);
77				}
78			} catch (InterruptedException e) {
79				return;
80			} catch (BogusException e) {
81				try {
82					// Give parent a chance to sleep
83					Thread.sleep(500);
84				} catch (InterruptedException x) {
85				}
86				parent.interrupt();
87				while (!Thread.currentThread().isInterrupted()) {
88					// Don't hog the CPU
89					try {
90						Thread.sleep(50);
91					} catch (InterruptedException x) {
92						// This is what we've been waiting for...don't throw it
93						// away!
94						break;
95					}
96				}
97			}
98		}
99
100		public void zz() throws BogusException {
101		}
102
103		public ResSupThread(Thread t) {
104			parent = t;
105		}
106
107		public synchronized int getCheckVal() {
108			return checkVal;
109		}
110	}
111
112	static class BogusException extends Throwable {
113
114        private static final long serialVersionUID = 1L;
115
116        public BogusException(String s) {
117			super(s);
118		}
119	}
120
121	Thread st, ct, spinner;
122
123	/**
124	 * @tests java.lang.Thread#Thread(java.lang.Runnable)
125	 */
126	public void test_ConstructorLjava_lang_Runnable() {
127            // Test for method java.lang.Thread(java.lang.Runnable)
128            ct = new Thread(new SimpleThread(10));
129            ct.start();
130	}
131
132	/**
133	 * @tests java.lang.Thread#Thread(java.lang.Runnable, java.lang.String)
134	 */
135	public void test_ConstructorLjava_lang_RunnableLjava_lang_String() {
136		// Test for method java.lang.Thread(java.lang.Runnable,
137		// java.lang.String)
138		Thread st1 = new Thread(new SimpleThread(1), "SimpleThread1");
139		assertEquals("Constructed thread with incorrect thread name", "SimpleThread1", st1
140				.getName());
141		st1.start();
142	}
143
144	/**
145	 * @tests java.lang.Thread#Thread(java.lang.String)
146	 */
147	public void test_ConstructorLjava_lang_String() {
148		// Test for method java.lang.Thread(java.lang.String)
149		Thread t = new Thread("Testing");
150		assertEquals("Created tread with incorrect name",
151				"Testing", t.getName());
152		t.start();
153	}
154
155	/**
156	 * @tests java.lang.Thread#Thread(java.lang.ThreadGroup, java.lang.Runnable)
157	 */
158	public void test_ConstructorLjava_lang_ThreadGroupLjava_lang_Runnable() {
159		// Test for method java.lang.Thread(java.lang.ThreadGroup,
160		// java.lang.Runnable)
161		ThreadGroup tg = new ThreadGroup("Test Group1");
162		st = new Thread(tg, new SimpleThread(1), "SimpleThread2");
163		assertTrue("Returned incorrect thread group", st.getThreadGroup() == tg);
164		st.start();
165		try {
166			st.join();
167		} catch (InterruptedException e) {
168		}
169		tg.destroy();
170	}
171
172	/**
173	 * @tests java.lang.Thread#Thread(java.lang.ThreadGroup, java.lang.Runnable,
174	 *        java.lang.String)
175	 */
176	public void test_ConstructorLjava_lang_ThreadGroupLjava_lang_RunnableLjava_lang_String() {
177		// Test for method java.lang.Thread(java.lang.ThreadGroup,
178		// java.lang.Runnable, java.lang.String)
179		ThreadGroup tg = new ThreadGroup("Test Group2");
180		st = new Thread(tg, new SimpleThread(1), "SimpleThread3");
181		assertTrue("Constructed incorrect thread", (st.getThreadGroup() == tg)
182				&& st.getName().equals("SimpleThread3"));
183		st.start();
184		try {
185			st.join();
186		} catch (InterruptedException e) {
187		}
188		tg.destroy();
189
190		Runnable r = new Runnable() {
191			public void run() {
192			}
193		};
194
195		ThreadGroup foo = null;
196		try {
197			new Thread(foo = new ThreadGroup("foo"), r, null);
198			// Should not get here
199			fail("Null cannot be accepted as Thread name");
200		} catch (NullPointerException npe) {
201			assertTrue("Null cannot be accepted as Thread name", true);
202			foo.destroy();
203		}
204
205	}
206
207	/**
208	 * @tests java.lang.Thread#Thread(java.lang.ThreadGroup, java.lang.String)
209	 */
210	public void test_ConstructorLjava_lang_ThreadGroupLjava_lang_String() {
211		// Test for method java.lang.Thread(java.lang.ThreadGroup,
212		// java.lang.String)
213		st = new Thread(new SimpleThread(1), "SimpleThread4");
214		assertEquals("Returned incorrect thread name",
215				"SimpleThread4", st.getName());
216		st.start();
217	}
218
219	/**
220	 * @tests java.lang.Thread#activeCount()
221	 */
222	public void test_activeCount() {
223		// Test for method int java.lang.Thread.activeCount()
224		Thread t = new Thread(new SimpleThread(10));
225		int active = 0;
226		synchronized (t) {
227			t.start();
228			active = Thread.activeCount();
229		}
230		assertTrue("Incorrect activeCount for current group: " + active, active > 1);
231		try {
232			t.join();
233		} catch (InterruptedException e) {
234		}
235	}
236
237	/**
238	 * @tests java.lang.Thread#checkAccess()
239	 */
240	public void test_checkAccess() {
241		// Test for method void java.lang.Thread.checkAccess()
242		ThreadGroup tg = new ThreadGroup("Test Group3");
243		try {
244			st = new Thread(tg, new SimpleThread(1), "SimpleThread5");
245			st.checkAccess();
246			assertTrue("CheckAccess passed", true);
247		} catch (SecurityException e) {
248			fail("CheckAccess failed : " + e.getMessage());
249		}
250		st.start();
251		try {
252			st.join();
253		} catch (InterruptedException e) {
254		}
255		tg.destroy();
256	}
257
258	/**
259     * @tests java.lang.Thread#countStackFrames()
260     */
261    @SuppressWarnings("deprecation")
262    public void test_countStackFrames() {
263        /*
264         * Thread.countStackFrames() is unpredictable, so we just test that it
265         * doesn't throw an exception.
266         */
267        Thread.currentThread().countStackFrames();
268    }
269
270	/**
271	 * @tests java.lang.Thread#currentThread()
272	 */
273	public void test_currentThread() {
274	    assertNotNull(Thread.currentThread());
275	}
276
277	/**
278	 * @tests java.lang.Thread#destroy()
279	 */
280	@SuppressWarnings("deprecation")
281    public void test_destroy() {
282	    try {
283	        new Thread().destroy();
284            // FIXME uncomment when IBM VME is updated
285            //fail("NoSuchMethodError was not thrown");
286        } catch (NoSuchMethodError e) {
287        }
288	}
289
290	/**
291	 * @tests java.lang.Thread#enumerate(java.lang.Thread[])
292	 */
293    public void test_enumerate$Ljava_lang_Thread() {
294        // Test for method int java.lang.Thread.enumerate(java.lang.Thread [])
295        // The test has been updated according to HARMONY-1974 JIRA issue.
296
297    	class MyThread extends Thread {
298            MyThread(ThreadGroup tg, String name) {
299                super(tg, name);
300            }
301
302            boolean failed = false;
303            String failMessage = null;
304
305            public void run() {
306            	SimpleThread st1 = null;
307            	SimpleThread st2 = null;
308            	ThreadGroup mytg = null;
309            	Thread firstOne = null;
310            	Thread secondOne = null;
311                try {
312                    int arrayLength = 10;
313                    Thread[] tarray = new Thread[arrayLength];
314                    st1 = new SimpleThread(-1);
315                    st2 = new SimpleThread(-1);
316                    mytg = new ThreadGroup("jp");
317                    firstOne = new Thread(mytg, st1, "firstOne2");
318                    secondOne = new Thread(mytg, st2, "secondOne1");
319                    int count = Thread.enumerate(tarray);
320                    assertEquals("Incorrect value returned1",
321                            1, count);
322                    synchronized (st1) {
323                        firstOne.start();
324                        try {
325                            st1.wait();
326                        } catch (InterruptedException e) {
327                        }
328                    }
329                    count = Thread.enumerate(tarray);
330                    assertEquals("Incorrect value returned2",
331                            2, count);
332                    synchronized (st2) {
333                        secondOne.start();
334                        try {
335                            st2.wait();
336                        } catch (InterruptedException e) {
337                        }
338                    }
339                    count = Thread.enumerate(tarray);
340                    assertEquals("Incorrect value returned3",
341                            3, count);
342                } catch (junit.framework.AssertionFailedError e) {
343                    failed = true;
344                    failMessage = e.getMessage();
345                } finally {
346                    synchronized (st1) {
347                        firstOne.interrupt();
348                    }
349                    synchronized (st2) {
350                        secondOne.interrupt();
351                    }
352                    try {
353                        firstOne.join();
354                        secondOne.join();
355                    } catch (InterruptedException e) {
356                    }
357                    mytg.destroy();
358                }
359            }
360        };
361
362        ThreadGroup tg = new ThreadGroup("tg");
363        MyThread t = new MyThread(tg, "top");
364        t.start();
365        try {
366            t.join();
367        } catch (InterruptedException e) {
368            fail("Unexpected interrupt");
369        } finally {
370            tg.destroy();
371        }
372        assertFalse(t.failMessage, t.failed);
373    }
374
375	/**
376	 * @tests java.lang.Thread#getContextClassLoader()
377	 */
378	public void test_getContextClassLoader() {
379		// Test for method java.lang.ClassLoader
380		// java.lang.Thread.getContextClassLoader()
381		Thread t = new Thread();
382		assertTrue("Incorrect class loader returned",
383				t.getContextClassLoader() == Thread.currentThread()
384						.getContextClassLoader());
385		t.start();
386
387	}
388
389	/**
390	 * @tests java.lang.Thread#getName()
391	 */
392	public void test_getName() {
393		// Test for method java.lang.String java.lang.Thread.getName()
394		st = new Thread(new SimpleThread(1), "SimpleThread6");
395		assertEquals("Returned incorrect thread name",
396				"SimpleThread6", st.getName());
397		st.start();
398	}
399
400	/**
401	 * @tests java.lang.Thread#getPriority()
402	 */
403	public void test_getPriority() {
404		// Test for method int java.lang.Thread.getPriority()
405		st = new Thread(new SimpleThread(1));
406		st.setPriority(Thread.MAX_PRIORITY);
407		assertTrue("Returned incorrect thread priority",
408				st.getPriority() == Thread.MAX_PRIORITY);
409		st.start();
410	}
411
412	/**
413	 * @tests java.lang.Thread#getThreadGroup()
414	 */
415	public void test_getThreadGroup() {
416		// Test for method java.lang.ThreadGroup
417		// java.lang.Thread.getThreadGroup()
418		ThreadGroup tg = new ThreadGroup("Test Group4");
419		st = new Thread(tg, new SimpleThread(1), "SimpleThread8");
420		assertTrue("Returned incorrect thread group", st.getThreadGroup() == tg);
421		st.start();
422		try {
423			st.join();
424		} catch (InterruptedException e) {
425		}
426		assertNull("group should be null", st.getThreadGroup());
427		assertNotNull("toString() should not be null", st.toString());
428		tg.destroy();
429
430		final Object lock = new Object();
431		Thread t = new Thread() {
432			@Override
433            public void run() {
434				synchronized (lock) {
435					lock.notifyAll();
436				}
437			}
438		};
439		synchronized (lock) {
440			t.start();
441			try {
442				lock.wait();
443			} catch (InterruptedException e) {
444			}
445		}
446		int running = 0;
447		while (t.isAlive())
448			running++;
449		ThreadGroup group = t.getThreadGroup();
450		assertNull("ThreadGroup is not null", group);
451	}
452
453	/**
454	 * @tests java.lang.Thread#interrupt()
455	 */
456	public void test_interrupt() {
457		// Test for method void java.lang.Thread.interrupt()
458		final Object lock = new Object();
459		class ChildThread1 extends Thread {
460			Thread parent;
461
462			boolean sync;
463
464			@Override
465            public void run() {
466				if (sync) {
467					synchronized (lock) {
468						lock.notify();
469						try {
470							lock.wait();
471						} catch (InterruptedException e) {
472						}
473					}
474				}
475				parent.interrupt();
476			}
477
478			public ChildThread1(Thread p, String name, boolean sync) {
479				super(name);
480				parent = p;
481				this.sync = sync;
482			}
483		}
484		boolean interrupted = false;
485		try {
486			ct = new ChildThread1(Thread.currentThread(), "Interrupt Test1",
487					false);
488			synchronized (lock) {
489				ct.start();
490				lock.wait();
491			}
492		} catch (InterruptedException e) {
493			interrupted = true;
494		}
495		assertTrue("Failed to Interrupt thread1", interrupted);
496
497		interrupted = false;
498		try {
499			ct = new ChildThread1(Thread.currentThread(), "Interrupt Test2",
500					true);
501			synchronized (lock) {
502				ct.start();
503				lock.wait();
504				lock.notify();
505			}
506			Thread.sleep(20000);
507		} catch (InterruptedException e) {
508			interrupted = true;
509		}
510		assertTrue("Failed to Interrupt thread2", interrupted);
511
512	}
513
514	/**
515	 * @tests java.lang.Thread#interrupted()
516	 */
517	public void test_interrupted() {
518        assertFalse("Interrupted returned true for non-interrupted thread", Thread
519                .interrupted());
520        Thread.currentThread().interrupt();
521        assertTrue("Interrupted returned true for non-interrupted thread", Thread.interrupted());
522        assertFalse("Failed to clear interrupted flag", Thread.interrupted());
523    }
524
525	/**
526	 * @tests java.lang.Thread#isAlive()
527	 */
528	public void test_isAlive() {
529		// Test for method boolean java.lang.Thread.isAlive()
530		SimpleThread simple;
531		st = new Thread(simple = new SimpleThread(500));
532		assertFalse("A thread that wasn't started is alive.", st.isAlive());
533		synchronized (simple) {
534			st.start();
535			try {
536				simple.wait();
537			} catch (InterruptedException e) {
538			}
539		}
540		assertTrue("Started thread returned false", st.isAlive());
541		try {
542			st.join();
543		} catch (InterruptedException e) {
544			fail("Thread did not die");
545		}
546		assertTrue("Stopped thread returned true", !st.isAlive());
547	}
548
549	/**
550	 * @tests java.lang.Thread#isDaemon()
551	 */
552	public void test_isDaemon() {
553		// Test for method boolean java.lang.Thread.isDaemon()
554		st = new Thread(new SimpleThread(1), "SimpleThread10");
555		assertTrue("Non-Daemon thread returned true", !st.isDaemon());
556		st.setDaemon(true);
557		assertTrue("Daemon thread returned false", st.isDaemon());
558		st.start();
559	}
560
561	/**
562	 * @tests java.lang.Thread#isInterrupted()
563	 */
564	public void test_isInterrupted() {
565		// Test for method boolean java.lang.Thread.isInterrupted()
566		class SpinThread implements Runnable {
567			public volatile boolean done = false;
568
569			public void run() {
570				while (!Thread.currentThread().isInterrupted())
571					;
572				while (!done)
573					;
574			}
575		}
576
577		SpinThread spin = new SpinThread();
578		spinner = new Thread(spin);
579		spinner.start();
580		Thread.yield();
581		try {
582			assertTrue("Non-Interrupted thread returned true", !spinner
583					.isInterrupted());
584			spinner.interrupt();
585			assertTrue("Interrupted thread returned false", spinner
586					.isInterrupted());
587			spin.done = true;
588		} finally {
589			spinner.interrupt();
590			spin.done = true;
591		}
592	}
593
594	/**
595	 * @tests java.lang.Thread#join()
596	 */
597	public void test_join() {
598		// Test for method void java.lang.Thread.join()
599		SimpleThread simple;
600		try {
601			st = new Thread(simple = new SimpleThread(100));
602			// cause isAlive() to be compiled by the JIT, as it must be called
603			// within 100ms below.
604			assertTrue("Thread is alive", !st.isAlive());
605			synchronized (simple) {
606				st.start();
607				simple.wait();
608			}
609			st.join();
610		} catch (InterruptedException e) {
611			fail("Join failed ");
612		}
613		assertTrue("Joined thread is still alive", !st.isAlive());
614		boolean result = true;
615		Thread th = new Thread("test");
616		try {
617			th.join();
618		} catch (InterruptedException e) {
619			result = false;
620		}
621		assertTrue("Hung joining a non-started thread", result);
622		th.start();
623	}
624
625	/**
626	 * @tests java.lang.Thread#join(long)
627	 */
628	public void test_joinJ() {
629		// Test for method void java.lang.Thread.join(long)
630		SimpleThread simple;
631		try {
632			st = new Thread(simple = new SimpleThread(1000), "SimpleThread12");
633			// cause isAlive() to be compiled by the JIT, as it must be called
634			// within 100ms below.
635			assertTrue("Thread is alive", !st.isAlive());
636			synchronized (simple) {
637				st.start();
638				simple.wait();
639			}
640			st.join(10);
641		} catch (InterruptedException e) {
642			fail("Join failed ");
643		}
644		assertTrue("Join failed to timeout", st.isAlive());
645
646		st.interrupt();
647		try {
648			st = new Thread(simple = new SimpleThread(100), "SimpleThread13");
649			synchronized (simple) {
650				st.start();
651				simple.wait();
652			}
653			st.join(1000);
654		} catch (InterruptedException e) {
655			fail("Join failed : " + e.getMessage());
656			return;
657		}
658		assertTrue("Joined thread is still alive", !st.isAlive());
659
660		final Object lock = new Object();
661		final Thread main = Thread.currentThread();
662		Thread killer = new Thread(new Runnable() {
663			public void run() {
664				try {
665					synchronized (lock) {
666						lock.notify();
667					}
668					Thread.sleep(100);
669				} catch (InterruptedException e) {
670					return;
671				}
672				main.interrupt();
673			}
674		});
675		boolean result = true;
676		Thread th = new Thread("test");
677		try {
678			synchronized (lock) {
679				killer.start();
680				lock.wait();
681			}
682			th.join(200);
683		} catch (InterruptedException e) {
684			result = false;
685		}
686		killer.interrupt();
687		assertTrue("Hung joining a non-started thread", result);
688		th.start();
689	}
690
691	/**
692	 * @tests java.lang.Thread#join(long, int)
693	 */
694	public void test_joinJI() throws Exception {
695		// Test for method void java.lang.Thread.join(long, int)
696		SimpleThread simple;
697                st = new Thread(simple = new SimpleThread(1000), "Squawk1");
698                assertTrue("Thread is alive", !st.isAlive());
699                synchronized (simple) {
700                        st.start();
701                        simple.wait();
702                }
703
704                long firstRead = System.currentTimeMillis();
705                st.join(100, 999999);
706                long secondRead = System.currentTimeMillis();
707                assertTrue("Did not join by appropriate time: " + secondRead + "-"
708                                + firstRead + "=" + (secondRead - firstRead), secondRead
709                                - firstRead <= 300);
710                assertTrue("Joined thread is not alive", st.isAlive());
711                st.interrupt();
712
713		final Object lock = new Object();
714		final Thread main = Thread.currentThread();
715		Thread killer = new Thread(new Runnable() {
716			public void run() {
717				try {
718					synchronized (lock) {
719						lock.notify();
720					}
721					Thread.sleep(100);
722				} catch (InterruptedException e) {
723					return;
724				}
725				main.interrupt();
726			}
727		});
728		boolean result = true;
729		Thread th = new Thread("test");
730		try {
731			synchronized (lock) {
732				killer.start();
733				lock.wait();
734			}
735			th.join(200, 20);
736		} catch (InterruptedException e) {
737			result = false;
738		}
739		killer.interrupt();
740		assertTrue("Hung joining a non-started thread", result);
741		th.start();
742	}
743
744	/**
745	 * @tests java.lang.Thread#run()
746	 */
747	public void test_run() {
748		// Test for method void java.lang.Thread.run()
749		class RunThread implements Runnable {
750			boolean didThreadRun = false;
751
752			public void run() {
753				didThreadRun = true;
754			}
755		}
756		RunThread rt = new RunThread();
757		Thread t = new Thread(rt);
758		try {
759			t.start();
760			int count = 0;
761			while (!rt.didThreadRun && count < 20) {
762				Thread.sleep(100);
763				count++;
764			}
765			assertTrue("Thread did not run", rt.didThreadRun);
766			t.join();
767		} catch (InterruptedException e) {
768			assertTrue("Joined thread was interrupted", true);
769		}
770		assertTrue("Joined thread is still alive", !t.isAlive());
771	}
772
773	/**
774	 * @tests java.lang.Thread#setDaemon(boolean)
775	 */
776	public void test_setDaemonZ() {
777		// Test for method void java.lang.Thread.setDaemon(boolean)
778		st = new Thread(new SimpleThread(1), "SimpleThread14");
779		st.setDaemon(true);
780		assertTrue("Failed to set thread as daemon thread", st.isDaemon());
781		st.start();
782	}
783
784	/**
785	 * @tests java.lang.Thread#setName(java.lang.String)
786	 */
787	public void test_setNameLjava_lang_String() {
788		// Test for method void java.lang.Thread.setName(java.lang.String)
789		st = new Thread(new SimpleThread(1), "SimpleThread15");
790		st.setName("Bogus Name");
791		assertEquals("Failed to set thread name",
792				"Bogus Name", st.getName());
793		try {
794			st.setName(null);
795			fail("Null should not be accepted as a valid name");
796		} catch (NullPointerException e) {
797			// success
798			assertTrue("Null should not be accepted as a valid name", true);
799		}
800		st.start();
801	}
802
803	/**
804	 * @tests java.lang.Thread#setPriority(int)
805	 */
806	public void test_setPriorityI() {
807		// Test for method void java.lang.Thread.setPriority(int)
808		st = new Thread(new SimpleThread(1));
809		st.setPriority(Thread.MAX_PRIORITY);
810		assertTrue("Failed to set priority",
811				st.getPriority() == Thread.MAX_PRIORITY);
812		st.start();
813	}
814
815	/**
816	 * @tests java.lang.Thread#sleep(long)
817	 */
818	public void test_sleepJ() {
819		// Test for method void java.lang.Thread.sleep(long)
820
821		// TODO : Test needs enhancing.
822		long stime = 0, ftime = 0;
823		try {
824			stime = System.currentTimeMillis();
825			Thread.sleep(1000);
826			ftime = System.currentTimeMillis();
827		} catch (InterruptedException e) {
828			fail("Unexpected interrupt received");
829		}
830		assertTrue("Failed to sleep long enough", (ftime - stime) >= 800);
831	}
832
833	/**
834	 * @tests java.lang.Thread#sleep(long, int)
835	 */
836	public void test_sleepJI() {
837		// Test for method void java.lang.Thread.sleep(long, int)
838
839		// TODO : Test needs revisiting.
840		long stime = 0, ftime = 0;
841		try {
842			stime = System.currentTimeMillis();
843			Thread.sleep(1000, 999999);
844			ftime = System.currentTimeMillis();
845		} catch (InterruptedException e) {
846			fail("Unexpected interrupt received");
847		}
848		long result = ftime - stime;
849		assertTrue("Failed to sleep long enough: " + result, result >= 900
850				&& result <= 1100);
851	}
852
853	/**
854	 * @tests java.lang.Thread#start()
855	 */
856	public void test_start() {
857		// Test for method void java.lang.Thread.start()
858		try {
859			ResSupThread t = new ResSupThread(Thread.currentThread());
860			synchronized (t) {
861				ct = new Thread(t, "Interrupt Test4");
862				ct.start();
863				t.wait();
864			}
865			assertTrue("Thread is not running1", ct.isAlive());
866			// Let the child thread get going.
867			int orgval = t.getCheckVal();
868			Thread.sleep(150);
869			assertTrue("Thread is not running2", orgval != t.getCheckVal());
870			ct.interrupt();
871		} catch (InterruptedException e) {
872			fail("Unexpected interrupt occurred");
873		}
874	}
875
876	/**
877	 * @tests java.lang.Thread#toString()
878	 */
879	public void test_toString() {
880		// Test for method java.lang.String java.lang.Thread.toString()
881		ThreadGroup tg = new ThreadGroup("Test Group5");
882		st = new Thread(tg, new SimpleThread(1), "SimpleThread17");
883		final String stString = st.toString();
884		final String expected = "Thread[SimpleThread17,5,Test Group5]";
885		assertTrue("Returned incorrect string: " + stString + "\t(expecting :"
886				+ expected + ")", stString.equals(expected));
887		st.start();
888		try {
889			st.join();
890		} catch (InterruptedException e) {
891		}
892		tg.destroy();
893	}
894
895    /**
896     * @tests java.lang.Thread#getAllStackTraces()
897     */
898    public void test_getAllStackTraces() {
899        Map<Thread, StackTraceElement[]> stMap = Thread.getAllStackTraces();
900        assertNotNull(stMap);
901        //TODO add security-based tests
902    }
903
904    /**
905     * @tests java.lang.Thread#getDefaultUncaughtExceptionHandler
906     * @tests java.lang.Thread#setDefaultUncaughtExceptionHandler
907     */
908    public void test_get_setDefaultUncaughtExceptionHandler() {
909        class Handler implements UncaughtExceptionHandler {
910            public void uncaughtException(Thread thread, Throwable ex) {
911            }
912        }
913
914        final Handler handler = new Handler();
915        Thread.setDefaultUncaughtExceptionHandler(handler);
916        assertSame(handler, Thread.getDefaultUncaughtExceptionHandler());
917
918        Thread.setDefaultUncaughtExceptionHandler(null);
919        assertNull(Thread.getDefaultUncaughtExceptionHandler());
920        //TODO add security-based tests
921    }
922
923    /**
924     * @tests java.lang.Thread#getStackTrace()
925     */
926    public void test_getStackTrace() {
927        StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
928
929        assertNotNull(stackTrace);
930
931        stack_trace_loop: {
932            for (int i = 0; i < stackTrace.length; i++) {
933                StackTraceElement e = stackTrace[i];
934                if (getClass().getName().equals(e.getClassName())) {
935                    if ("test_getStackTrace".equals(e.getMethodName())) {
936                        break stack_trace_loop;
937                    }
938                }
939            }
940            fail("class and method not found in stack trace");
941        }
942
943        //TODO add security-based tests
944    }
945
946    /**
947     * @tests java.lang.Thread#getState()
948     */
949    public void test_getState() {
950        Thread.State state = Thread.currentThread().getState();
951        assertNotNull(state);
952        assertEquals(Thread.State.RUNNABLE, state);
953        //TODO add additional state tests
954    }
955
956    /**
957     * @tests java.lang.Thread#getUncaughtExceptionHandler
958     * @tests java.lang.Thread#setUncaughtExceptionHandler
959     */
960    public void test_get_setUncaughtExceptionHandler() {
961        class Handler implements UncaughtExceptionHandler {
962            public void uncaughtException(Thread thread, Throwable ex) {
963            }
964        }
965
966        final Handler handler = new Handler();
967        Thread.currentThread().setUncaughtExceptionHandler(handler);
968        assertSame(handler, Thread.currentThread().getUncaughtExceptionHandler());
969
970        Thread.currentThread().setUncaughtExceptionHandler(null);
971
972        //TODO add security-based tests
973    }
974
975    /**
976     * @tests java.lang.Thread#getId()
977     */
978    public void test_getId() {
979        assertTrue("current thread's ID is not positive", Thread.currentThread().getId() > 0);
980
981        //check all the current threads for positive IDs
982        Map<Thread, StackTraceElement[]> stMap = Thread.getAllStackTraces();
983        for (Thread thread : stMap.keySet()) {
984            assertTrue("thread's ID is not positive: " + thread.getName(), thread.getId() > 0);
985        }
986    }
987
988
989	@Override
990    protected void tearDown() {
991		try {
992			if (st != null)
993				st.interrupt();
994		} catch (Exception e) {
995		}
996		try {
997			if (spinner != null)
998				spinner.interrupt();
999		} catch (Exception e) {
1000		}
1001		try {
1002			if (ct != null)
1003				ct.interrupt();
1004		} catch (Exception e) {
1005		}
1006
1007		try {
1008			spinner = null;
1009			st = null;
1010			ct = null;
1011			System.runFinalization();
1012		} catch (Exception e) {
1013		}
1014	}
1015}
1016