1 // ThreadTest.cs - NUnit Test Cases for the System.Threading.Thread class
2 //
3 // Authors
4 //	Eduardo Garcia Cebollero (kiwnix@yahoo.es)
5 //	Sebastien Pouliot  <sebastien@ximian.com>
6 //
7 // (C) Eduardo Garcia Cebollero.
8 // (C) Ximian, Inc.  http://www.ximian.com
9 // (C) 2004 Novell (http://www.novell.com)
10 //
11 
12 using System;
13 using System.Globalization;
14 using System.Security.Principal;
15 using System.Threading;
16 using System.Threading.Tasks;
17 using System.Reflection;
18 using System.Collections.Generic;
19 using SD = System.Diagnostics;
20 
21 using NUnit.Framework;
22 
23 namespace MonoTests.System.Threading
24 {
25 	// These tests seem to hang the 2.0 framework. So they are disabled for now
26 	// Don't reenable them until you can run a few thousand times on an SMP box.
27 	[Category ("NotWorking")]
28 	public class ThreadedPrincipalTest
29 	{
NoPrincipal()30 		public static void NoPrincipal ()
31 		{
32 			AppDomain.CurrentDomain.SetPrincipalPolicy (PrincipalPolicy.NoPrincipal);
33 			IPrincipal p = Thread.CurrentPrincipal;
34 			Assert.IsNull (p, "#1");
35 
36 			Thread.CurrentPrincipal = new GenericPrincipal (new GenericIdentity ("mono"), null);
37 			Assert.IsNotNull (Thread.CurrentPrincipal, "#2");
38 
39 			Thread.CurrentPrincipal = null;
40 			Assert.IsNull (Thread.CurrentPrincipal, "#3");
41 			// in this case we can return to null
42 		}
43 
UnauthenticatedPrincipal()44 		public static void UnauthenticatedPrincipal ()
45 		{
46 			AppDomain.CurrentDomain.SetPrincipalPolicy (PrincipalPolicy.UnauthenticatedPrincipal);
47 			IPrincipal p = Thread.CurrentPrincipal;
48 			Assert.IsNotNull (p, "#1");
49 			Assert.IsTrue ((p is GenericPrincipal), "#2");
50 			Assert.AreEqual (String.Empty, p.Identity.Name, "#3");
51 			Assert.AreEqual (String.Empty, p.Identity.AuthenticationType, "#4");
52 			Assert.IsFalse (p.Identity.IsAuthenticated, "#5");
53 
54 			Thread.CurrentPrincipal = new GenericPrincipal (new GenericIdentity ("mono"), null);
55 			Assert.IsNotNull (Thread.CurrentPrincipal, "#6");
56 
57 			Thread.CurrentPrincipal = null;
58 			Assert.IsNotNull (Thread.CurrentPrincipal, "#7");
59 			// in this case we can't return to null
60 		}
61 
WindowsPrincipal()62 		public static void WindowsPrincipal ()
63 		{
64 			AppDomain.CurrentDomain.SetPrincipalPolicy (PrincipalPolicy.WindowsPrincipal);
65 			IPrincipal p = Thread.CurrentPrincipal;
66 			Assert.IsNotNull (p, "#1");
67 			Assert.IsTrue ((p is WindowsPrincipal), "#2");
68 			Assert.IsNotNull (p.Identity.Name, "#3");
69 			Assert.IsNotNull (p.Identity.AuthenticationType, "#4");
70 			Assert.IsTrue (p.Identity.IsAuthenticated, "#5");
71 
72 			// note: we can switch from a WindowsPrincipal to a GenericPrincipal
73 			Thread.CurrentPrincipal = new GenericPrincipal (new GenericIdentity ("mono"), null);
74 			Assert.IsNotNull (Thread.CurrentPrincipal, "#6");
75 
76 			Thread.CurrentPrincipal = null;
77 			Assert.IsNotNull (Thread.CurrentPrincipal, "#7");
78 			// in this case we can't return to null
79 		}
80 
CopyOnNewThread()81 		public static void CopyOnNewThread ()
82 		{
83 			Assert.IsNotNull (Thread.CurrentPrincipal, "#1");
84 			Assert.AreEqual ("good", Thread.CurrentPrincipal.Identity.Name, "#2");
85 		}
86 	}
87 
88 	[TestFixture]
89 	[Category("MobileNotWorking")] // Abort #10240
90 	public class ThreadTest
91 	{
92 		//TimeSpan Infinite = new TimeSpan (-10000);	// -10000 ticks == -1 ms
93 		TimeSpan SmallNegative = new TimeSpan (-2);	// between 0 and -1.0 (infinite) ms
94 		TimeSpan Negative = new TimeSpan (-20000);	// really negative
95 		//TimeSpan MaxValue = TimeSpan.FromMilliseconds ((long) Int32.MaxValue);
96 		TimeSpan TooLarge = TimeSpan.FromMilliseconds ((long) Int32.MaxValue + 1);
97 
98 		//Some Classes to test as threads
99 		private class C1Test
100 		{
101 			public int cnt;
102 			public Thread thread1;
103 			public bool endm1;
104 			public bool endm2;
105 
C1Test()106 			public C1Test()
107 			{
108 				thread1 = (Thread)null;
109 				this.cnt = 0;
110 				endm1 = endm2 = false;
111 			}
112 
TestMethod()113 			public void TestMethod()
114 			{
115 				while (cnt < 10)
116 				{
117 					cnt++;
118 				}
119 				endm1 = true;
120 			}
TestMethod2()121 			public void TestMethod2()
122 			{
123 				if (!(thread1==(Thread)null) )
124 				{
125 					thread1.Join();
126 				}
127 				endm2 = true;
128 			}
129 		}
130 
131 		private class C2Test
132 		{
133 			public int cnt;
134 			public bool run = false;
135 
C2Test()136 			public C2Test()
137 			{
138 				this.cnt = 0;
139 			}
140 
TestMethod()141 			public void TestMethod()
142 			{
143 				run = true;
144 				while (true)
145 				{
146 					if (cnt < 1000)
147 						cnt++;
148 					else
149 						cnt = 0;
150 				}
151 			}
152 		}
153 
154 		private class C3Test
155 		{
156 			public C1Test sub_class;
157 			public Thread sub_thread;
158 
C3Test()159 			public C3Test()
160 			{
161 				sub_class = new C1Test();
162 				sub_thread = new Thread(new ThreadStart(sub_class.TestMethod));
163 			}
164 
TestMethod1()165 			public void TestMethod1()
166 			{
167 				sub_thread.Start();
168 				Thread.Sleep (100);
169 #if MONO_FEATURE_THREAD_ABORT
170 				sub_thread.Abort();
171 #else
172 				sub_thread.Interrupt ();
173 #endif
174 			}
175 		}
176 
177 		private class C4Test
178 		{
179 			public C1Test class1;
180 			public C1Test class2;
181 			public Thread thread1;
182 			public Thread thread2;
183 			public bool T1ON ;
184 			public bool T2ON ;
185 
C4Test()186 			public C4Test()
187 			{
188 				T1ON = false;
189 				T2ON = false;
190 				class1 = new C1Test();
191 				class2 = new C1Test();
192 				thread1 = new Thread(new ThreadStart(class1.TestMethod));
193 				thread2 = new Thread(new ThreadStart(class2.TestMethod));
194 			}
195 
TestMethod1()196 			public void TestMethod1()
197 			{
198 				thread1.Start();
199 				TestUtil.WaitForAlive (thread1, "wait1");
200 				T1ON = true;
201 				thread2.Start();
202 				TestUtil.WaitForAlive (thread2, "wait2");
203 				T2ON = true;
204 #if MONO_FEATURE_THREAD_ABORT
205 				thread1.Abort();
206 #else
207 				thread1.Interrupt ();
208 #endif
209 				TestUtil.WaitForNotAlive (thread1, "wait3");
210 				T1ON = false;
211 #if MONO_FEATURE_THREAD_ABORT
212 				thread2.Abort();
213 #else
214 				thread2.Interrupt ();
215 #endif
216 				TestUtil.WaitForNotAlive (thread2, "wait4");
217 				T2ON = false;
218 			}
219 
TestMethod2()220 			public void TestMethod2()
221 			{
222 				thread1.Start();
223 				thread1.Join();
224 			}
225 		}
226 
227 		[Test]
TestCtor1()228 		public void TestCtor1()
229 		{
230 			C1Test test1 = new C1Test();
231 			Thread t = new Thread (new ThreadStart (test1.TestMethod));
232 
233 			Assert.IsTrue (t.CurrentCulture.IsReadOnly, "CurrentCulture.IsReadOnly");
234 			Assert.IsFalse (t.IsAlive, "IsAlive");
235 			Assert.IsFalse (t.IsBackground, "IsBackground");
236 			Assert.IsNull (t.Name, "Name");
237 			Assert.AreEqual (ThreadState.Unstarted, t.ThreadState, "ThreadState");
238 		}
239 
240 		[Test]
241 		[Category ("NotWorking")] // we're not sharing (read-only) CultureInfo
CultureInfo_Shared_Across_Threads()242 		public void CultureInfo_Shared_Across_Threads ()
243 		{
244 			Thread t = new Thread (TestCtor1);
245 			Assert.AreSame (t.CurrentCulture, t.CurrentUICulture, "Culture");
246 
247 			Assert.AreSame (t.CurrentCulture, CultureInfo.CurrentCulture, "CultureInfo.CurrentCulture");
248 			Assert.AreSame (t.CurrentUICulture, CultureInfo.CurrentUICulture, "CultureInfo.CurrentUICulture");
249 
250 			Assert.AreSame (t.CurrentCulture, Thread.CurrentThread.CurrentCulture, "Thread.CurrentThread.CurrentCulture");
251 			Assert.AreSame (t.CurrentUICulture, Thread.CurrentThread.CurrentUICulture, "Thread.CurrentThread.CurrentUICulture");
252 		}
253 
254 		[Test] // bug #325566
GetHashCodeTest()255 		public void GetHashCodeTest ()
256 		{
257 			C1Test test1 = new C1Test ();
258 			Thread tA = new Thread (new ThreadStart (test1.TestMethod));
259 			int hA1 = tA.GetHashCode ();
260 			Assert.IsTrue (hA1 > 0, "#A1");
261 			tA.Start ();
262 			int hA2 = tA.GetHashCode ();
263 			Assert.AreEqual (hA1, hA2, "#A2");
264 			tA.Join ();
265 			int hA3 = tA.GetHashCode ();
266 			Assert.AreEqual (hA1, hA3, "#A3");
267 			Assert.AreEqual (hA1, tA.ManagedThreadId, "#A4");
268 
269 			test1 = new C1Test ();
270 			Thread tB = new Thread (new ThreadStart (test1.TestMethod));
271 			int hB1 = tB.GetHashCode ();
272 			Assert.IsTrue (hB1 > 0, "#B1");
273 			tB.Start ();
274 			int hB2 = tB.GetHashCode ();
275 			Assert.AreEqual (hB1, hB2, "#B2");
276 			tB.Join ();
277 			int hB3 = tB.GetHashCode ();
278 			Assert.AreEqual (hB1, hB3, "#B3");
279 			Assert.AreEqual (hB1, tB.ManagedThreadId, "#B4");
280 			Assert.IsFalse (hA2 == hB2, "#B5");
281 		}
282 
283 		[Test] // bug #82700
ManagedThreadId()284 		public void ManagedThreadId ()
285 		{
286 			C1Test test1 = new C1Test ();
287 			Thread t1 = new Thread (new ThreadStart (test1.TestMethod));
288 			int mtA1 = t1.ManagedThreadId;
289 			t1.Start ();
290 			int mtA2 = t1.ManagedThreadId;
291 			t1.Join ();
292 			int mtA3 = t1.ManagedThreadId;
293 			Assert.AreEqual (mtA1, mtA2, "#A1");
294 			Assert.AreEqual (mtA2, mtA3, "#A2");
295 
296 			test1 = new C1Test ();
297 			Thread t2 = new Thread (new ThreadStart (test1.TestMethod));
298 			int mtB1 = t2.ManagedThreadId;
299 			t2.Start ();
300 			int mtB2 = t2.ManagedThreadId;
301 			t2.Join ();
302 			int mtB3 = t2.ManagedThreadId;
303 			Assert.AreEqual (mtB1, mtB2, "#B1");
304 			Assert.AreEqual (mtB2, mtB3, "#B2");
305 			Assert.IsFalse (mtB1 == mtA1, "#B3");
306 		}
307 
308 		[Test]
309 		[Category ("NotDotNet")] // it hangs.
310 		[Category ("InterpreterNotWorking")] /* crashes on linux/arm64 */
TestStart()311 		public void TestStart()
312 		{
313 		{
314 			C1Test test1 = new C1Test();
315 			Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
316 			TestThread.Start();
317 			TestThread.Join();
318 			Assert.AreEqual (10, test1.cnt, "#1");
319 		}
320 		{
321 			C2Test test1 = new C2Test();
322 			Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
323 			TestThread.Start();
324 #if MONO_FEATURE_THREAD_ABORT
325 			TestThread.Abort();
326 #else
327 			TestThread.Interrupt ();
328 #endif
329 			try {
330 				TestThread.Start();
331 				Assert.Fail ("#2");
332 			} catch (ThreadStateException) {
333 			}
334 		}
335 		{
336 			C2Test test1 = new C2Test();
337 			Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
338 			TestThread.Start();
339 			while (!test1.run) {
340 			}
341 			bool started = (TestThread.ThreadState == ThreadState.Running);
342 			Assert.AreEqual (started, test1.run, "#15 Thread Is not in the correct state: ");
343 #if MONO_FEATURE_THREAD_ABORT
344 			TestThread.Abort();
345 #else
346 			TestThread.Interrupt ();
347 #endif
348 		}
349 		}
350 
351 		[Test]
TestApartmentState()352 		public void TestApartmentState ()
353 		{
354 			C2Test test1 = new C2Test();
355 			Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
356 			Assert.AreEqual (ApartmentState.Unknown, TestThread.ApartmentState, "#1");
357 			TestThread.Start();
358 			TestUtil.WaitForAlive (TestThread, "wait5");
359 			Assert.AreEqual (ApartmentState.MTA, TestThread.ApartmentState, "#2");
360 #if MONO_FEATURE_THREAD_ABORT
361 			TestThread.Abort();
362 #else
363 			TestThread.Interrupt ();
364 #endif
365 		}
366 
367 		[Test]
368 		[Category ("NotWorking")] // setting the priority of a Thread before it is started isn't implemented in Mono yet
TestPriority1()369 		public void TestPriority1()
370 		{
371 			C2Test test1 = new C2Test();
372 			Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
373 			try {
374 				TestThread.Priority=ThreadPriority.BelowNormal;
375 				ThreadPriority before = TestThread.Priority;
376 				Assert.AreEqual (ThreadPriority.BelowNormal, before, "#40 Unexpected priority before thread start: ");
377 				TestThread.Start();
378 				TestUtil.WaitForAlive (TestThread, "wait7");
379 				ThreadPriority after = TestThread.Priority;
380 				Assert.AreEqual (before, after, "#41 Unexpected Priority Change: ");
381 			} finally {
382 #if MONO_FEATURE_THREAD_ABORT
383 				TestThread.Abort();
384 #else
385 				TestThread.Interrupt ();
386 #endif
387 			}
388 		}
389 
390 #if MONO_FEATURE_THREAD_ABORT
391 		[Test]
392 		[Category ("NotDotNet")] // on MS, Thread is still in AbortRequested state when Start is invoked
AbortUnstarted()393 		public void AbortUnstarted ()
394 		{
395 			C2Test test1 = new C2Test();
396 			Thread th = new Thread (new ThreadStart (test1.TestMethod));
397 			th.Abort ();
398 			th.Start ();
399 		}
400 #endif
401 
402 		[Test]
403 		[Category ("NotDotNet")] // on MS, ThreadState is immediately Stopped after Abort
404 		[Category ("NotWorking")] // this is a MonoTODO -> no support for Priority
TestPriority2()405 		public void TestPriority2()
406 		{
407 			C2Test test1 = new C2Test();
408 			Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
409 			try {
410 				Assert.AreEqual (ThreadPriority.Normal, TestThread.Priority, "#42 Incorrect Priority in New thread: ");
411 				TestThread.Start();
412 				TestUtil.WaitForAliveOrStop (TestThread, "wait8");
413 				Assert.AreEqual (ThreadPriority.Normal, TestThread.Priority, "#43 Incorrect Priority in Started thread: ");
414 			} finally {
415 #if MONO_FEATURE_THREAD_ABORT
416 				TestThread.Abort();
417 #else
418 				TestThread.Interrupt ();
419 #endif
420 			}
421 			Assert.AreEqual (ThreadPriority.Normal, TestThread.Priority, "#44 Incorrect Priority in Aborted thread: ");
422 		}
423 
424 		[Test]
425 		[Category ("NotWorking")] // this is a MonoTODO -> no support for Priority
TestPriority3()426 		public void TestPriority3()
427 		{
428 			C2Test test1 = new C2Test();
429 			Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
430 			try {
431 				TestThread.Start();
432 				TestThread.Priority = ThreadPriority.Lowest;
433 				Assert.AreEqual (ThreadPriority.Lowest, TestThread.Priority, "#45A Incorrect Priority:");
434 				TestThread.Priority = ThreadPriority.BelowNormal;
435 				Assert.AreEqual (ThreadPriority.BelowNormal, TestThread.Priority, "#45B Incorrect Priority:");
436 				TestThread.Priority = ThreadPriority.Normal;
437 				Assert.AreEqual (ThreadPriority.Normal, TestThread.Priority, "#45C Incorrect Priority:");
438 				TestThread.Priority = ThreadPriority.AboveNormal;
439 				Assert.AreEqual (ThreadPriority.AboveNormal, TestThread.Priority, "#45D Incorrect Priority:");
440 				TestThread.Priority = ThreadPriority.Highest;
441 				Assert.AreEqual (ThreadPriority.Highest, TestThread.Priority, "#45E Incorrect Priority:");
442 			}
443 			finally {
444 #if MONO_FEATURE_THREAD_ABORT
445 				TestThread.Abort();
446 #else
447 				TestThread.Interrupt ();
448 #endif
449 			}
450 		}
451 
452 		[Test]
453 		[Category ("InterpreterNotWorking")]
TestUndivisibleByPageSizeMaxStackSize()454 		public void TestUndivisibleByPageSizeMaxStackSize ()
455 		{
456 			const int undivisible_stacksize = 1048573;
457 
458 			var thread = new Thread (new ThreadStart (delegate {}), undivisible_stacksize);
459 			thread.Start ();
460 			thread.Join ();
461 		}
462 
463 		[Test]
TestIsBackground1()464 		public void TestIsBackground1 ()
465 		{
466 			C2Test test1 = new C2Test();
467 			Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
468 			try {
469 				TestThread.Start();
470 				TestUtil.WaitForAlive (TestThread, "wait9");
471 				bool state = TestThread.IsBackground;
472 				Assert.IsFalse (state, "#51 IsBackground not set at the default state: ");
473 			} finally {
474 #if MONO_FEATURE_THREAD_ABORT
475 				TestThread.Abort();
476 #else
477 				TestThread.Interrupt ();
478 #endif
479 			}
480 		}
481 
482 		[Test]
TestIsBackground2()483 		public void TestIsBackground2 ()
484 		{
485 			C2Test test1 = new C2Test();
486 			Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
487 			TestThread.IsBackground = true;
488 			try {
489 				TestThread.Start();
490 			} finally {
491 #if MONO_FEATURE_THREAD_ABORT
492 				TestThread.Abort();
493 #else
494 				TestThread.Interrupt ();
495 #endif
496 			}
497 
498 			if (TestThread.IsAlive) {
499 				try {
500 					Assert.IsTrue (TestThread.IsBackground, "#52 Is Background Changed to Start ");
501 				} catch (ThreadStateException) {
502 					// Ignore if thread died meantime
503 				}
504 			}
505 		}
506 
507 		[Test]
TestName()508 		public void TestName()
509 		{
510 			C2Test test1 = new C2Test();
511 			Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
512 			try {
513 				TestThread.Start();
514 				TestUtil.WaitForAlive (TestThread, "wait10");
515 				string name = TestThread.Name;
516 				Assert.IsNull (name, "#61 Name set when mustn't be set: ");
517 				string newname = "Testing....";
518 				TestThread.Name = newname;
519 				Assert.AreEqual (newname, TestThread.Name, "#62 Name not set when must be set: ");
520 			} finally {
521 #if MONO_FEATURE_THREAD_ABORT
522 				TestThread.Abort();
523 #else
524 				TestThread.Interrupt ();
525 #endif
526 			}
527 		}
528 
529 		[Test]
Name()530 		public void Name ()
531 		{
532 			Thread t = new Thread (new ThreadStart (Name));
533 			Assert.IsNull (t.Name, "Name-1");
534 			t.Name = null;
535 			Assert.IsNull (t.Name, "Name-2");
536 		}
537 
538 		[Test]
539 		[ExpectedException (typeof (InvalidOperationException))]
Rename()540 		public void Rename ()
541 		{
542 			Thread t = new Thread (new ThreadStart (Rename));
543 			t.Name = "a";
544 			t.Name = "b";
545 		}
546 
547 		[Test]
TestNestedThreads1()548 		public void TestNestedThreads1()
549 		{
550 			C3Test test1 = new C3Test();
551 			Thread TestThread = new Thread(new ThreadStart(test1.TestMethod1));
552 			try {
553 				TestThread.Start();
554 				TestUtil.WaitForAlive (TestThread, "wait11");
555 			} finally {
556 #if MONO_FEATURE_THREAD_ABORT
557 				TestThread.Abort();
558 #else
559 				TestThread.Interrupt ();
560 #endif
561 			}
562 		}
563 
564 		[Test]
TestNestedThreads2()565 		public void TestNestedThreads2()
566 		{
567 			C4Test test1 = new C4Test();
568 			Thread TestThread = new Thread(new ThreadStart(test1.TestMethod1));
569 			try {
570 				TestThread.Start();
571 			} finally {
572 #if MONO_FEATURE_THREAD_ABORT
573 				TestThread.Abort();
574 #else
575 				TestThread.Interrupt ();
576 #endif
577 			}
578 		}
579 
580 		[Test]
TestJoin1()581 		public void TestJoin1()
582 		{
583 			C1Test test1 = new C1Test();
584 			C1Test test2 = new C1Test();
585 			Thread thread1 = new Thread(new ThreadStart(test1.TestMethod));
586 			Thread thread2 = new Thread(new ThreadStart(test1.TestMethod2));
587 			try {
588 				thread1.Start();
589 				thread2.Start();
590 				thread2.Join();
591 			} finally {
592 #if MONO_FEATURE_THREAD_ABORT
593 				thread1.Abort();
594 				thread2.Abort();
595 #else
596 				thread1.Interrupt ();
597 				thread2.Interrupt ();
598 #endif
599 			}
600 		}
601 
602 		[Test]
603 		[ExpectedException (typeof (ArgumentOutOfRangeException))]
Join_Int32_Negative()604 		public void Join_Int32_Negative ()
605 		{
606 			// -1 is Timeout.Infinite
607 			Thread.CurrentThread.Join (-2);
608 		}
609 
610 		[Test]
611 		[ExpectedException (typeof (ArgumentOutOfRangeException))]
Join_TimeSpan_Negative()612 		public void Join_TimeSpan_Negative ()
613 		{
614 			Thread.CurrentThread.Join (Negative);
615 		}
616 
617 		[Test]
618 		[ExpectedException (typeof (ArgumentOutOfRangeException))]
Join_TimeSpan_TooLarge()619 		public void Join_TimeSpan_TooLarge ()
620 		{
621 			Thread.CurrentThread.Join (TooLarge);
622 		}
623 
624 		[Test]
Join_TimeSpan_SmallNegative()625 		public void Join_TimeSpan_SmallNegative ()
626 		{
627 			Thread.CurrentThread.Join (SmallNegative);
628 		}
629 
630 		[Test]
631 		[ExpectedException (typeof (ArgumentOutOfRangeException))]
Sleep_Int32_Negative()632 		public void Sleep_Int32_Negative ()
633 		{
634 			// -1 is Timeout.Infinite
635 			Thread.Sleep (-2);
636 		}
637 
638 		[Test]
Sleep_TimeSpan_SmallNegative()639 		public void Sleep_TimeSpan_SmallNegative ()
640 		{
641 			Thread.Sleep (SmallNegative);
642 		}
643 
644 		[Test]
645 		[ExpectedException (typeof (ArgumentOutOfRangeException))]
Sleep_TimeSpan_Negative()646 		public void Sleep_TimeSpan_Negative ()
647 		{
648 			Thread.Sleep (Negative);
649 		}
650 
651 		[Test]
652 		[ExpectedException (typeof (ArgumentOutOfRangeException))]
Sleep_TimeSpan_TooLarge()653 		public void Sleep_TimeSpan_TooLarge ()
654 		{
655 			Thread.Sleep (TooLarge);
656 		}
657 
658 		[Test]
SpinWait()659 		public void SpinWait ()
660 		{
661 			// no exception for negative numbers
662 			Thread.SpinWait (Int32.MinValue);
663 			Thread.SpinWait (0);
664 		}
665 
666 		[Test]
TestThreadState()667 		public void TestThreadState ()
668 		{
669 			//TODO: Test The rest of the possible transitions
670 			C2Test test1 = new C2Test();
671 			Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
672 			Assert.AreEqual (ThreadState.Unstarted, TestThread.ThreadState, "#101 Wrong Thread State");
673 			try {
674 				TestThread.Start();
675 				//while(!TestThread.IsAlive); //In the MS Documentation this is not necessary
676 											  //but in the MS SDK it is
677 				Assert.IsTrue (TestThread.ThreadState == ThreadState.Running || (TestThread.ThreadState & ThreadState.Unstarted) != 0,
678 					"#102 Wrong Thread State: " + TestThread.ThreadState.ToString ());
679 			} finally {
680 #if MONO_FEATURE_THREAD_ABORT
681 				TestThread.Abort();
682 #else
683 				TestThread.Interrupt ();
684 #endif
685 			}
686 
687 			TestUtil.WaitForNotAlive (TestThread, "wait12");
688 			// Docs say state will be Stopped, but Aborted happens sometimes (?)
689 			Assert.IsTrue ((ThreadState.Stopped & TestThread.ThreadState) != 0 || (ThreadState.Aborted & TestThread.ThreadState) != 0,
690 				"#103 Wrong Thread State: " + TestThread.ThreadState.ToString ());
691 		}
692 
693 		[Test]
694 		[Ignore ("see comment below.")]
CurrentPrincipal_PrincipalPolicy_NoPrincipal()695 		public void CurrentPrincipal_PrincipalPolicy_NoPrincipal ()
696 		{
697 			// note: switching from PrincipalPolicy won't work inside the same thread
698 			// because as soon as a Principal object is created the Policy doesn't matter anymore
699 			Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.NoPrincipal));
700 			try {
701 				t.Start ();
702 				t.Join ();
703 			} catch {
704 #if MONO_FEATURE_THREAD_ABORT
705 				t.Abort ();
706 #else
707 				t.Interrupt ();
708 #endif
709 			}
710 		}
711 
712 		[Test]
713 		[Ignore ("see comment below.")]
CurrentPrincipal_PrincipalPolicy_UnauthenticatedPrincipal()714 		public void CurrentPrincipal_PrincipalPolicy_UnauthenticatedPrincipal ()
715 		{
716 			// note: switching from PrincipalPolicy won't work inside the same thread
717 			// because as soon as a Principal object is created the Policy doesn't matter anymore
718 			Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.UnauthenticatedPrincipal));
719 			try {
720 				t.Start ();
721 				t.Join ();
722 			} catch {
723 #if MONO_FEATURE_THREAD_ABORT
724 				t.Abort ();
725 #else
726 				t.Interrupt ();
727 #endif
728 			}
729 		}
730 
731 		[Test]
CurrentPrincipal_PrincipalPolicy_WindowsPrincipal()732 		public void CurrentPrincipal_PrincipalPolicy_WindowsPrincipal ()
733 		{
734 			// note: switching from PrincipalPolicy won't work inside the same thread
735 			// because as soon as a Principal object is created the Policy doesn't matter anymore
736 			Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.WindowsPrincipal));
737 			try {
738 				t.Start ();
739 				t.Join ();
740 			} catch {
741 #if MONO_FEATURE_THREAD_ABORT
742 				t.Abort ();
743 #else
744 				t.Interrupt ();
745 #endif
746 			}
747 		}
748 
749 		[Test]
IPrincipal_CopyOnNewThread()750 		public void IPrincipal_CopyOnNewThread ()
751 		{
752 			Thread.CurrentPrincipal = new GenericPrincipal (new GenericIdentity ("bad"), null);
753 			Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.CopyOnNewThread));
754 			try {
755 				Thread.CurrentPrincipal = new GenericPrincipal (new GenericIdentity ("good"), null);
756 				t.Start ();
757 				t.Join ();
758 			} catch {
759 #if MONO_FEATURE_THREAD_ABORT
760 				t.Abort ();
761 #else
762 				t.Interrupt ();
763 #endif
764 			}
765 		}
766 
767 		int counter = 0;
768 
769 #if MONO_FEATURE_THREAD_SUSPEND_RESUME
770 		[Test]
TestSuspend()771 		public void TestSuspend ()
772 		{
773 			Thread t = new Thread (new ThreadStart (DoCount));
774 			t.IsBackground = true;
775 			t.Start ();
776 
777 			CheckIsRunning ("t1", t);
778 
779 			t.Suspend ();
780 			WaitSuspended ("t2", t);
781 
782 			CheckIsNotRunning ("t3", t);
783 
784 			t.Resume ();
785 			WaitResumed ("t4", t);
786 
787 			CheckIsRunning ("t5", t);
788 
789 			t.Abort ();
790 			TestUtil.WaitForNotAlive (t, "wait13");
791 			CheckIsNotRunning ("t6", t);
792 		}
793 #endif
794 
795 #if MONO_FEATURE_THREAD_SUSPEND_RESUME && MONO_FEATURE_THREAD_ABORT
796 		[Test]
797 		[Category("NotDotNet")] // On MS, ThreadStateException is thrown on Abort: "Thread is suspended; attempting to abort"
TestSuspendAbort()798 		public void TestSuspendAbort ()
799 		{
800 			Thread t = new Thread (new ThreadStart (DoCount));
801 			t.IsBackground = true;
802 			t.Start ();
803 
804 			CheckIsRunning ("t1", t);
805 
806 			t.Suspend ();
807 			WaitSuspended ("t2", t);
808 
809 			CheckIsNotRunning ("t3", t);
810 
811 			t.Abort ();
812 
813 			int n=0;
814 			while (t.IsAlive && n < 200) {
815 				Thread.Sleep (10);
816 				n++;
817 			}
818 
819 			Assert.IsTrue (n < 200, "Timeout while waiting for abort");
820 
821 			CheckIsNotRunning ("t6", t);
822 		}
823 #endif
824 
825 		[Test]
Test_Interrupt()826 		public void Test_Interrupt ()
827 		{
828 			ManualResetEvent mre = new ManualResetEvent (false);
829 			bool interruptedExceptionThrown = false;
830 
831 			ThreadPool.QueueUserWorkItem (Test_Interrupt_Worker, Thread.CurrentThread);
832 
833 			try {
834 				try {
835 					mre.WaitOne (3000);
836 				} finally {
837 					try {
838 						mre.WaitOne (0);
839 					} catch (ThreadInterruptedException) {
840 						Assert.Fail ("ThreadInterruptedException thrown twice");
841 					}
842 				}
843 			} catch (ThreadInterruptedException) {
844 				interruptedExceptionThrown = true;
845 			}
846 
847 			Assert.IsTrue (interruptedExceptionThrown, "ThreadInterruptedException expected.");
848 		}
849 
850 		[Test]
851 		[ExpectedException (typeof (ArgumentNullException))]
TestQueueUserWorkItemNullCallback()852 		public void TestQueueUserWorkItemNullCallback ()
853 		{
854 			ThreadPool.QueueUserWorkItem (null, null);
855 		}
856 
Test_Interrupt_Worker(object o)857 		private void Test_Interrupt_Worker (object o)
858 		{
859 			Thread t = o as Thread;
860 			Thread.Sleep (100);
861 			t.Interrupt ();
862 		}
863 
864 		[Test]
Test_InterruptCurrentThread()865 		public void Test_InterruptCurrentThread ()
866 		{
867 			ManualResetEvent mre = new ManualResetEvent (false);
868 			bool interruptedExceptionThrown = false;
869 
870 			Thread.CurrentThread.Interrupt ();
871 			try {
872 				mre.WaitOne (0);
873 				Assert.Fail ();
874 			} catch (ThreadInterruptedException) {
875 			}
876 		}
877 
878 		[Test]
GetNamedDataSlotTest()879 		public void GetNamedDataSlotTest ()
880 		{
881 			Assert.IsNotNull (Thread.GetNamedDataSlot ("te#st"), "#1");
882 			Assert.AreSame (Thread.GetNamedDataSlot ("te#st"), Thread.GetNamedDataSlot ("te#st"), "#2");
883 		}
884 
885 		class DomainClass : MarshalByRefObject {
886 			Thread m_thread;
887 			bool success;
888 
Run()889 			public bool Run () {
890 				m_thread = new Thread(ThreadProc);
891 				m_thread.Start(Thread.CurrentThread);
892 				m_thread.Join();
893 				return success;
894 			}
895 
ThreadProc(object arg)896 			public void ThreadProc (object arg) {
897 				success = m_thread == Thread.CurrentThread;
898 			}
899 		}
900 
901 #if MONO_FEATURE_MULTIPLE_APPDOMAINS
902 		[Test]
903 		[Category ("NotDotNet")]
CurrentThread_Domains()904 		public void CurrentThread_Domains ()
905 		{
906 			AppDomain ad = AppDomain.CreateDomain ("foo");
907 			ad.Load (typeof (DomainClass).Assembly.GetName ());
908 			var o = (DomainClass)ad.CreateInstanceAndUnwrap (typeof (DomainClass).Assembly.FullName, typeof (DomainClass).FullName);
909 			Assert.IsTrue (o.Run ());
910 			AppDomain.Unload (ad);
911 		}
912 #endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
913 
914 		[Test]
SetNameInThreadPoolThread()915 		public void SetNameInThreadPoolThread ()
916 		{
917 			Task t = Task.Run (delegate () {
918 				Thread.CurrentThread.Name = "ThreadName1";
919 				Assert.AreEqual (Thread.CurrentThread.Name, "ThreadName1", "#1");
920 
921 				try {
922 					Thread.CurrentThread.Name = "ThreadName2";
923 					Assert.Fail ("#2");
924 				} catch (InvalidOperationException) {
925 				}
926 			});
927 
928 			t.Wait ();
929 		}
930 
CheckIsRunning(string s, Thread t)931 		void CheckIsRunning (string s, Thread t)
932 		{
933 			int c = counter;
934 			Thread.Sleep (100);
935 			Assert.IsTrue (counter > c, s);
936 		}
937 
CheckIsNotRunning(string s, Thread t)938 		void CheckIsNotRunning (string s, Thread t)
939 		{
940 			int c = counter;
941 			Thread.Sleep (100);
942 			Assert.AreEqual (counter, c, s);
943 		}
944 
WaitSuspended(string s, Thread t)945 		void WaitSuspended (string s, Thread t)
946 		{
947 			int n=0;
948 			ThreadState state = t.ThreadState;
949 			while ((state & ThreadState.Suspended) == 0) {
950 				Assert.IsTrue ((state & ThreadState.SuspendRequested) != 0, s + ": expected SuspendRequested state");
951 				Thread.Sleep (10);
952 				n++;
953 				Assert.IsTrue (n < 100, s + ": failed to suspend");
954 				state = t.ThreadState;
955 			}
956 			Assert.IsTrue ((state & ThreadState.SuspendRequested) == 0, s + ": SuspendRequested state not expected");
957 		}
958 
WaitResumed(string s, Thread t)959 		void WaitResumed (string s, Thread t)
960 		{
961 			int n=0;
962 			while ((t.ThreadState & ThreadState.Suspended) != 0) {
963 				Thread.Sleep (10);
964 				n++;
965 				Assert.IsTrue (n < 100, s + ": failed to resume");
966 			}
967 		}
968 
DoCount()969 		public void DoCount ()
970 		{
971 			while (true) {
972 				counter++;
973 				Thread.Sleep (1);
974 			}
975 		}
976 	}
977 
978 	[TestFixture]
979 	public class ThreadStateTest {
Start()980 		void Start ()
981 		{
982 		}
983 
984 		[Test] // bug #81720
IsBackGround()985 		public void IsBackGround ()
986 		{
987 			Thread t1 = new Thread (new ThreadStart (Start));
988 			Assert.AreEqual (ThreadState.Unstarted, t1.ThreadState, "#A1");
989 			Assert.IsFalse (t1.IsBackground, "#A2");
990 			t1.Start ();
991 			t1.Join ();
992 			Assert.AreEqual (ThreadState.Stopped, t1.ThreadState, "#A3");
993 
994 			try {
995 				bool isBackGround = t1.IsBackground;
996 				Assert.Fail ("#A4: " + isBackGround.ToString ());
997 			} catch (ThreadStateException ex) {
998 				Assert.AreEqual (typeof (ThreadStateException), ex.GetType (), "#A5");
999 				Assert.IsNull (ex.InnerException, "#A6");
1000 				Assert.IsNotNull (ex.Message, "#A7");
1001 			}
1002 
1003 			Thread t2 = new Thread (new ThreadStart (Start));
1004 			Assert.AreEqual (ThreadState.Unstarted, t2.ThreadState, "#B1");
1005 			t2.IsBackground = true;
1006 			Assert.AreEqual (ThreadState.Unstarted | ThreadState.Background, t2.ThreadState, "#B2");
1007 			Assert.IsTrue (t2.IsBackground, "#B3");
1008 			t2.Start ();
1009 			t2.Join ();
1010 			Assert.AreEqual (ThreadState.Stopped, t2.ThreadState, "#B4");
1011 
1012 			try {
1013 				bool isBackGround = t2.IsBackground;
1014 				Assert.Fail ("#B5: " + isBackGround.ToString ());
1015 			} catch (ThreadStateException ex) {
1016 				Assert.AreEqual (typeof (ThreadStateException), ex.GetType (), "#B6");
1017 				Assert.IsNull (ex.InnerException, "#B7");
1018 				Assert.IsNotNull (ex.Message, "#B8");
1019 			}
1020 		}
1021 
1022 		[Test] // bug #60031
StoppedThreadsThrowThreadStateException()1023 		public void StoppedThreadsThrowThreadStateException ()
1024 		{
1025 			var t = new Thread (() => { });
1026 			t.Start ();
1027 			t.Join ();
1028 
1029 			Assert.Throws<ThreadStateException> (() => { var isb = t.IsBackground; }, "IsBackground getter");
1030 			Assert.Throws<ThreadStateException> (() => { var isb = t.ApartmentState; }, "ApartmentState getter");
1031 			Assert.Throws<ThreadStateException> (() => t.ApartmentState = ApartmentState.MTA, "ApartmentState setter");
1032 			Assert.Throws<ThreadStateException> (() => t.IsBackground = false, "IsBackground setter");
1033 			Assert.Throws<ThreadStateException> (() => t.Start (), "Start ()");
1034 #if MONO_FEATURE_THREAD_SUSPEND_RESUME
1035 			Assert.Throws<ThreadStateException> (() => t.Resume (), "Resume ()");
1036 			Assert.Throws<ThreadStateException> (() => t.Suspend (), "Suspend ()");
1037 #endif
1038 			Assert.Throws<ThreadStateException> (() => t.GetApartmentState (), "GetApartmentState ()");
1039 			Assert.Throws<ThreadStateException> (() => t.SetApartmentState (ApartmentState.MTA), "SetApartmentState ()");
1040 			Assert.Throws<ThreadStateException> (() => t.TrySetApartmentState (ApartmentState.MTA), "TrySetApartmentState ()");
1041 		}
1042 	}
1043 
1044 	[TestFixture]
1045 	[Serializable]
1046 	public class ThreadTest_ManagedThreadId
1047 	{
1048 		AppDomain ad1;
1049 		AppDomain ad2;
1050 		MBRO mbro = new MBRO ();
1051 
1052 		class MBRO : MarshalByRefObject {
1053 			public int id_a1;
1054 			public int id_b1;
1055 			public int id_b2;
1056 			public string ad_a1;
1057 			public string ad_b1;
1058 			public string ad_b2;
1059 			public string message;
1060 		}
1061 #if !MOBILE
1062 		[Test]
ManagedThreadId_AppDomains()1063 		public void ManagedThreadId_AppDomains ()
1064 		{
1065 			AppDomain currentDomain = AppDomain.CurrentDomain;
1066 			ad1 = AppDomain.CreateDomain ("AppDomain 1", currentDomain.Evidence, currentDomain.SetupInformation);
1067 			ad2 = AppDomain.CreateDomain ("AppDomain 2", currentDomain.Evidence, currentDomain.SetupInformation);
1068 
1069 			Thread a = new Thread (ThreadA);
1070 			Thread b = new Thread (ThreadB);
1071 			// execute on AppDomain 1 thread A
1072 			// execute on AppDomain 2 thread B
1073 			// execute on AppDomain 1 thread B - must have same ManagedThreadId as Ad 2 on thread B
1074 			a.Start ();
1075 			a.Join ();
1076 			b.Start ();
1077 			b.Join ();
1078 
1079 			AppDomain.Unload (ad1);
1080 			AppDomain.Unload (ad2);
1081 
1082 			if (mbro.message != null)
1083 				Assert.Fail (mbro.message);
1084 
1085 			// Console.WriteLine ("Done id_a1: {0} id_b1: {1} id_b2: {2} ad_a1: {3} ad_b1: {4} ad_b2: {5}", mbro.id_a1, mbro.id_b1, mbro.id_b2, mbro.ad_a1, mbro.ad_b1, mbro.ad_b2);
1086 
1087 			Assert.AreEqual ("AppDomain 1", mbro.ad_a1, "Name #1");
1088 			Assert.AreEqual ("AppDomain 1", mbro.ad_b1, "Name #2");
1089 			Assert.AreEqual ("AppDomain 2", mbro.ad_b2, "Name #3");
1090 
1091 			Assert.AreNotEqual (mbro.id_a1, mbro.id_b1, "Id #1");
1092 			Assert.AreNotEqual (mbro.id_a1, mbro.id_b2, "Id #2");
1093 			Assert.AreEqual (mbro.id_b1, mbro.id_b2, "Id #3");
1094 
1095 			Assert.AreNotEqual (mbro.id_a1, Thread.CurrentThread.ManagedThreadId, "Id #4");
1096 			Assert.AreNotEqual (mbro.id_b1, Thread.CurrentThread.ManagedThreadId, "Id #5");
1097 			Assert.AreNotEqual (mbro.id_b2, Thread.CurrentThread.ManagedThreadId, "Id #6");
1098 			Assert.AreNotEqual (mbro.ad_a1, AppDomain.CurrentDomain.FriendlyName, "Name #4");
1099 			Assert.AreNotEqual (mbro.ad_b1, AppDomain.CurrentDomain.FriendlyName, "Name #5");
1100 			Assert.AreNotEqual (mbro.ad_b2, AppDomain.CurrentDomain.FriendlyName, "Name #6");
1101 		}
1102 #endif
A1()1103 		void A1 ()
1104 		{
1105 			mbro.id_a1 = Thread.CurrentThread.ManagedThreadId;
1106 			mbro.ad_a1 = AppDomain.CurrentDomain.FriendlyName;
1107 		}
1108 
B2()1109 		void B2 ()
1110 		{
1111 			mbro.id_b2 = Thread.CurrentThread.ManagedThreadId;
1112 			mbro.ad_b2 = AppDomain.CurrentDomain.FriendlyName;
1113 		}
1114 
B1()1115 		void B1 ()
1116 		{
1117 			mbro.id_b1 = Thread.CurrentThread.ManagedThreadId;
1118 			mbro.ad_b1 = AppDomain.CurrentDomain.FriendlyName;
1119 		}
1120 
ThreadA(object obj)1121 		void ThreadA (object obj)
1122 		{
1123 			// Console.WriteLine ("ThreadA");
1124 			try {
1125 				ad1.DoCallBack (A1);
1126 			} catch (Exception ex) {
1127 				mbro.message = string.Format ("ThreadA exception: {0}", ex);
1128 			}
1129 			// Console.WriteLine ("ThreadA Done");
1130 		}
1131 
ThreadB(object obj)1132 		void ThreadB (object obj)
1133 		{
1134 			// Console.WriteLine ("ThreadB");
1135 			try {
1136 				ad2.DoCallBack (B2);
1137 				ad1.DoCallBack (B1);
1138 			} catch (Exception ex) {
1139 				mbro.message = string.Format ("ThreadB exception: {0}", ex);
1140 			}
1141 			// Console.WriteLine ("ThreadB Done");
1142 		}
1143 	}
1144 
1145 	[TestFixture]
1146 	public class ThreadApartmentTest
1147 	{
Start()1148 		void Start ()
1149 		{
1150 		}
1151 
1152 		[Test] // bug #81658
ApartmentState_StoppedThread()1153 		public void ApartmentState_StoppedThread ()
1154 		{
1155 			Thread t1 = new Thread (new ThreadStart (Start));
1156 			t1.Start ();
1157 			t1.Join ();
1158 			try {
1159 				ApartmentState state = t1.ApartmentState;
1160 				Assert.Fail ("#A1: " + state.ToString ());
1161 			} catch (ThreadStateException ex) {
1162 				Assert.AreEqual (typeof (ThreadStateException), ex.GetType (), "#A2");
1163 				Assert.IsNull (ex.InnerException, "#A3");
1164 				Assert.IsNotNull (ex.Message, "#A4");
1165 			}
1166 
1167 			Thread t2 = new Thread (new ThreadStart (Start));
1168 			t2.IsBackground = true;
1169 			t2.Start ();
1170 			t2.Join ();
1171 			try {
1172 				ApartmentState state = t2.ApartmentState;
1173 				Assert.Fail ("#B1: " + state.ToString ());
1174 			} catch (ThreadStateException ex) {
1175 				Assert.AreEqual (typeof (ThreadStateException), ex.GetType (), "#B2");
1176 				Assert.IsNull (ex.InnerException, "#B3");
1177 				Assert.IsNotNull (ex.Message, "#B4");
1178 			}
1179 		}
1180 
1181 		[Test]
ApartmentState_BackGround()1182 		public void ApartmentState_BackGround ()
1183 		{
1184 			Thread t1 = new Thread (new ThreadStart (Start));
1185 			t1.IsBackground = true;
1186 			Assert.AreEqual (ApartmentState.Unknown, t1.ApartmentState, "#1");
1187 			t1.ApartmentState = ApartmentState.STA;
1188 			Assert.AreEqual (ApartmentState.STA, t1.ApartmentState, "#2");
1189 		}
1190 
1191 		[Test]
TestApartmentState()1192 		public void TestApartmentState ()
1193 		{
1194 			Thread t1 = new Thread (new ThreadStart (Start));
1195 			Thread t2 = new Thread (new ThreadStart (Start));
1196 			Thread t3 = new Thread (new ThreadStart (Start));
1197 
1198 			Assert.AreEqual (ApartmentState.Unknown, t1.ApartmentState, "Thread1 Default");
1199 			Assert.AreEqual (ApartmentState.Unknown, t2.ApartmentState, "Thread2 Default");
1200 			Assert.AreEqual (ApartmentState.Unknown, t3.ApartmentState, "Thread3 Default");
1201 
1202 			t1.ApartmentState = ApartmentState.STA;
1203 			Assert.AreEqual (ApartmentState.STA, t1.ApartmentState, "Thread1 Set Once");
1204 			t1.ApartmentState = ApartmentState.MTA;
1205 			Assert.AreEqual (ApartmentState.STA, t1.ApartmentState, "Thread1 Set Twice");
1206 
1207 			t2.ApartmentState = ApartmentState.MTA;
1208 			Assert.AreEqual (ApartmentState.MTA, t2.ApartmentState, "Thread2 Set Once");
1209 			t2.ApartmentState = ApartmentState.STA;
1210 			Assert.AreEqual (ApartmentState.MTA, t2.ApartmentState, "Thread2 Set Twice");
1211 
1212 			bool exception_occured = false;
1213 			try {
1214 				t3.ApartmentState = ApartmentState.Unknown;
1215 			}
1216 			catch (Exception) {
1217 				exception_occured = true;
1218 			}
1219 			Assert.AreEqual (ApartmentState.Unknown, t3.ApartmentState, "Thread3 Set Invalid");
1220 			Assert.IsFalse (exception_occured, "Thread3 Set Invalid Exception Occured");
1221 
1222 			t1.Start ();
1223 			exception_occured = false;
1224 			try {
1225 				t1.ApartmentState = ApartmentState.STA;
1226 			}
1227 			catch (Exception) {
1228 				exception_occured = true;
1229 			}
1230 			Assert.IsTrue (exception_occured, "Thread1 Started Invalid Exception Occured");
1231 		}
1232 
1233 		[Test]
TestSetApartmentStateSameState()1234 		public void TestSetApartmentStateSameState ()
1235 		{
1236 			Thread t1 = new Thread (new ThreadStart (Start));
1237 			t1.SetApartmentState (ApartmentState.STA);
1238 			Assert.AreEqual (ApartmentState.STA, t1.ApartmentState, "Thread1 Set Once");
1239 
1240 			t1.SetApartmentState (ApartmentState.STA);
1241 			Assert.AreEqual (ApartmentState.STA, t1.ApartmentState, "Thread1 Set twice");
1242 		}
1243 
1244 		[Test]
1245 		[ExpectedException(typeof(InvalidOperationException))]
TestSetApartmentStateDiffState()1246 		public void TestSetApartmentStateDiffState ()
1247 		{
1248 			Thread t1 = new Thread (new ThreadStart (Start));
1249 			t1.SetApartmentState (ApartmentState.STA);
1250 			Assert.AreEqual (ApartmentState.STA, t1.ApartmentState, "Thread1 Set Once");
1251 
1252 			t1.SetApartmentState (ApartmentState.MTA);
1253 		}
1254 
1255 		[Test]
TestTrySetApartmentState()1256 		public void TestTrySetApartmentState ()
1257 		{
1258 			Thread t1 = new Thread (new ThreadStart (Start));
1259 			t1.SetApartmentState (ApartmentState.STA);
1260 			Assert.AreEqual (ApartmentState.STA, t1.ApartmentState, "#1");
1261 
1262 			bool result = t1.TrySetApartmentState (ApartmentState.MTA);
1263 			Assert.IsFalse (result, "#2");
1264 
1265 			result = t1.TrySetApartmentState (ApartmentState.STA);
1266 			Assert.IsTrue (result, "#3");
1267 		}
1268 
1269 		[Test]
TestTrySetApartmentStateRunning()1270 		public void TestTrySetApartmentStateRunning ()
1271 		{
1272 			Thread t1 = new Thread (new ThreadStart (Start));
1273 			t1.SetApartmentState (ApartmentState.STA);
1274 			Assert.AreEqual (ApartmentState.STA, t1.ApartmentState, "#1");
1275 
1276 			t1.Start ();
1277 
1278 			try {
1279 				t1.TrySetApartmentState (ApartmentState.STA);
1280 				Assert.Fail ("#2");
1281 			} catch (ThreadStateException) {
1282 			}
1283 
1284 			t1.Join ();
1285 		}
1286 
1287 		[Test]
Volatile()1288 		public void Volatile () {
1289 			double v3 = 55667;
1290 			Thread.VolatileWrite (ref v3, double.MaxValue);
1291 			Assert.AreEqual (v3, double.MaxValue);
1292 
1293 			float v4 = 1;
1294 			Thread.VolatileWrite (ref v4, float.MaxValue);
1295 			Assert.AreEqual (v4, float.MaxValue);
1296 		}
1297 
1298 		[Test]
Culture()1299 		public void Culture ()
1300 		{
1301 			Assert.IsNotNull (Thread.CurrentThread.CurrentCulture, "CurrentCulture");
1302 			Assert.IsNotNull (Thread.CurrentThread.CurrentUICulture, "CurrentUICulture");
1303 		}
1304 
1305 		[Test]
ThreadStartSimple()1306 		public void ThreadStartSimple ()
1307 		{
1308 			int i = 0;
1309 			Thread t = new Thread (delegate () {
1310 				// ensure the NSAutoreleasePool works
1311 				i++;
1312 			});
1313 			t.Start ();
1314 			t.Join ();
1315 			Assert.AreEqual (1, i, "ThreadStart");
1316 		}
1317 
1318 		[Test]
ParametrizedThreadStart()1319 		public void ParametrizedThreadStart ()
1320 		{
1321 			int i = 0;
1322 			object arg = null;
1323 			Thread t = new Thread (delegate (object obj) {
1324 				// ensure the NSAutoreleasePool works
1325 				i++;
1326 				arg = obj;
1327 			});
1328 			t.Start (this);
1329 			t.Join ();
1330 
1331 			Assert.AreEqual (1, i, "ParametrizedThreadStart");
1332 			Assert.AreEqual (this, arg, "obj");
1333 		}
1334 
1335 		[Test]
SetNameTpThread()1336 		public void SetNameTpThread () {
1337 			ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
1338 		}
1339 
ThreadProc(Object stateInfo)1340 		static void ThreadProc(Object stateInfo) {
1341 			Thread.CurrentThread.Name = "My Worker";
1342 		}
1343 
1344 		[Test]
GetStackTraces()1345 		public void GetStackTraces () {
1346 			var m = typeof (Thread).GetMethod ("Mono_GetStackTraces", BindingFlags.NonPublic|BindingFlags.Static);
1347 			if (m != null) {
1348 				var res = (Dictionary<Thread,SD.StackTrace>)typeof (Thread).GetMethod ("Mono_GetStackTraces", BindingFlags.NonPublic|BindingFlags.Static).Invoke (null, null);
1349 				foreach (var t in res.Keys) {
1350 					var st = res [t].ToString ();
1351 				}
1352 			}
1353 		}
1354 	}
1355 
1356 	public class TestUtil
1357 	{
WaitForNotAlive(Thread t, string s)1358 		public static void WaitForNotAlive (Thread t, string s)
1359 		{
1360 			WhileAlive (t, true, s);
1361 		}
1362 
WaitForAlive(Thread t, string s)1363 		public static void WaitForAlive (Thread t, string s)
1364 		{
1365 			WhileAlive (t, false, s);
1366 		}
1367 
WaitForAliveOrStop(Thread t, string s)1368 		public static bool WaitForAliveOrStop (Thread t, string s)
1369 		{
1370 			return WhileAliveOrStop (t, false, s);
1371 		}
1372 
WhileAlive(Thread t, bool alive, string s)1373 		public static void WhileAlive (Thread t, bool alive, string s)
1374 		{
1375 			var sw = SD.Stopwatch.StartNew ();
1376 			while (t.IsAlive == alive) {
1377 				if (sw.Elapsed.TotalSeconds > 10) {
1378 					if (alive) Assert.Fail ("Timeout while waiting for not alive state. " + s);
1379 					else Assert.Fail ("Timeout while waiting for alive state. " + s);
1380 				}
1381 			}
1382 		}
1383 
WhileAliveOrStop(Thread t, bool alive, string s)1384 		public static bool WhileAliveOrStop (Thread t, bool alive, string s)
1385 		{
1386 			var sw = SD.Stopwatch.StartNew ();
1387 			while (t.IsAlive == alive) {
1388 				if (t.ThreadState == ThreadState.Stopped)
1389 					return false;
1390 
1391 				if (sw.Elapsed.TotalSeconds > 10) {
1392 					if (alive) Assert.Fail ("Timeout while waiting for not alive state. " + s);
1393 					else Assert.Fail ("Timeout while waiting for alive state. " + s);
1394 				}
1395 			}
1396 
1397 			return true;
1398 		}
1399 	}
1400 }
1401