f181c6815a9000ff8a0dbb1840cb1e41f3bc0acf
[mono.git] / mcs / class / corlib / Test / System.Threading / ThreadTest.cs
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.Security.Principal;
14 using System.Threading;
15
16 using NUnit.Framework;
17
18 namespace MonoTests.System.Threading
19 {
20         // These tests seem to hang the 2.0 framework. So they are disabled for now
21         // Don't reenable them until you can run a few thousand times on an SMP box.
22         [Category ("NotWorking")]
23         public class ThreadedPrincipalTest
24         {
25                 public static void NoPrincipal () 
26                 {
27 #if !TARGET_JVM // AppDomain.SetPrincipalPolicy not supported for TARGET_JVM
28                         AppDomain.CurrentDomain.SetPrincipalPolicy (PrincipalPolicy.NoPrincipal);
29 #endif
30                         IPrincipal p = Thread.CurrentPrincipal;
31                         Assert.IsNull (p, "#1");
32
33                         Thread.CurrentPrincipal = new GenericPrincipal (new GenericIdentity ("mono"), null);
34                         Assert.IsNotNull (Thread.CurrentPrincipal, "#2");
35
36                         Thread.CurrentPrincipal = null;
37                         Assert.IsNull (Thread.CurrentPrincipal, "#3");
38                         // in this case we can return to null
39                 }
40
41 #if !TARGET_JVM // AppDomain.SetPrincipalPolicy not supported for TARGET_JVM
42                 public static void UnauthenticatedPrincipal () 
43                 {
44                         AppDomain.CurrentDomain.SetPrincipalPolicy (PrincipalPolicy.UnauthenticatedPrincipal);
45                         IPrincipal p = Thread.CurrentPrincipal;
46                         Assert.IsNotNull (p, "#1");
47                         Assert.IsTrue ((p is GenericPrincipal), "#2");
48                         Assert.AreEqual (String.Empty, p.Identity.Name, "#3");
49                         Assert.AreEqual (String.Empty, p.Identity.AuthenticationType, "#4");
50                         Assert.IsFalse (p.Identity.IsAuthenticated, "#5");
51
52                         Thread.CurrentPrincipal = new GenericPrincipal (new GenericIdentity ("mono"), null);
53                         Assert.IsNotNull (Thread.CurrentPrincipal, "#6");
54
55                         Thread.CurrentPrincipal = null;
56                         Assert.IsNotNull (Thread.CurrentPrincipal, "#7");
57                         // in this case we can't return to null
58                 }
59
60                 public static void WindowsPrincipal () 
61                 {
62                         AppDomain.CurrentDomain.SetPrincipalPolicy (PrincipalPolicy.WindowsPrincipal);
63                         IPrincipal p = Thread.CurrentPrincipal;
64                         Assert.IsNotNull (p, "#1");
65                         Assert.IsTrue ((p is WindowsPrincipal), "#2");
66                         Assert.IsNotNull (p.Identity.Name, "#3");
67                         Assert.IsNotNull (p.Identity.AuthenticationType, "#4");
68                         Assert.IsTrue (p.Identity.IsAuthenticated, "#5");
69
70                         // note: we can switch from a WindowsPrincipal to a GenericPrincipal
71                         Thread.CurrentPrincipal = new GenericPrincipal (new GenericIdentity ("mono"), null);
72                         Assert.IsNotNull (Thread.CurrentPrincipal, "#6");
73
74                         Thread.CurrentPrincipal = null;
75                         Assert.IsNotNull (Thread.CurrentPrincipal, "#7");
76                         // in this case we can't return to null
77                 }
78 #endif // TARGET_JVM
79
80                 public static void CopyOnNewThread ()
81                 {
82                         Assert.IsNotNull (Thread.CurrentPrincipal, "#1");
83                         Assert.AreEqual ("good", Thread.CurrentPrincipal.Identity.Name, "#2");
84                 }
85         }
86
87         [TestFixture]
88         [Category ("NotWorking")]
89         public class ThreadTest
90         {
91                 //Some Classes to test as threads
92                 private class C1Test
93                 {
94                         public int cnt;
95                         public Thread thread1;
96                         public bool endm1;
97                         public bool endm2;
98
99                         public C1Test()
100                         {
101                                 thread1 = (Thread)null;
102                                 this.cnt = 0;
103                                 endm1 = endm2 = false;
104                         }
105                         
106                         public void TestMethod()
107                         {
108                                 while (cnt < 10)
109                                 {
110                                         cnt++;
111                                 }
112                                 endm1 = true;
113                         }
114                         public void TestMethod2()
115                         {
116                                 if (!(thread1==(Thread)null) )
117                                 {
118                                         thread1.Join();
119                                 }
120                                 endm2 = true;
121                         }
122                 }
123
124                 private class C2Test
125                 {
126                         public int cnt;
127                         public bool run = false;
128                         
129                         public C2Test()
130                         {
131                                 this.cnt = 0;
132                         }
133
134                         public void TestMethod()
135                         {
136                                 run = true;
137                                 while (true)
138                                 {
139                                         if (cnt < 1000)
140                                                 cnt++;
141                                         else
142                                                 cnt = 0;
143                                 }
144                         }
145                 }
146                 
147                 private class C3Test
148                 {
149                         public C1Test sub_class;
150                         public Thread sub_thread;
151
152                         public C3Test()
153                         {
154                                 sub_class = new C1Test();
155                                 sub_thread = new Thread(new ThreadStart(sub_class.TestMethod));
156                         }
157
158                         public void TestMethod1()
159                         {
160                                 sub_thread.Start();
161                                 Thread.Sleep (100);
162                                 sub_thread.Abort();
163                         }
164                 }
165                 
166                 private class C4Test
167                 {
168                         public C1Test class1;
169                         public C1Test class2;
170                         public Thread thread1;
171                         public Thread thread2;
172                         public bool T1ON ;
173                         public bool T2ON ;
174
175                         public C4Test()
176                         {
177                                 T1ON = false;
178                                 T2ON = false;
179                                 class1 = new C1Test();
180                                 class2 = new C1Test();
181                                 thread1 = new Thread(new ThreadStart(class1.TestMethod));
182                                 thread2 = new Thread(new ThreadStart(class2.TestMethod));
183                         }
184
185                         public void TestMethod1()
186                         {
187                                 thread1.Start();
188                                 TestUtil.WaitForAlive (thread1, "wait1");
189                                 T1ON = true;
190                                 thread2.Start();
191                                 TestUtil.WaitForAlive (thread2, "wait2");
192                                 T2ON = true;
193                                 thread1.Abort();
194                                 TestUtil.WaitForNotAlive (thread1, "wait3");
195                                 T1ON = false;
196                                 thread2.Abort();
197                                 TestUtil.WaitForNotAlive (thread2, "wait4");
198                                 T2ON = false;
199                         }
200                         
201                         public void TestMethod2()
202                         {
203                                 thread1.Start();
204                                 thread1.Join();
205                         }
206                 }
207
208                 public void TestCtor1()
209                 {                       
210                         C1Test test1 = new C1Test();
211                         try
212                         {
213                                 Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
214                         }
215                         catch (Exception e)
216                         {
217                                 Assert.Fail ("#01 Unexpected Exception Thrown: " + e.ToString ());
218                         }
219                 }
220
221                 [Category("NotDotNet")]
222                 public void TestStart()
223                 {
224                 {
225                         C1Test test1 = new C1Test();
226                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
227                         try
228                         {
229                                 TestThread.Start();
230                         }
231                         catch (Exception e)
232                         {
233                                 Assert.Fail ("#12 Unexpected Exception Thrown: " + e.ToString ());
234                         }
235                         TestThread.Join();
236                         Assert.AreEqual (10, test1.cnt, "#13 Thread Not started");
237                 }
238                 {
239                         bool errorThrown = false;
240                         C2Test test1 = new C2Test();
241                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
242                         TestThread.Start();
243                         TestThread.Abort();
244                         try
245                         {
246                                 TestThread.Start();
247                         }
248                         catch(ThreadStateException)
249                         {
250                                 errorThrown = true;
251                         }
252                         Assert.IsTrue (errorThrown, "#14 no ThreadStateException trown");
253                 }
254                 {
255                         C2Test test1 = new C2Test();
256                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
257                         TestThread.Start();
258                         while(!test1.run);
259                         bool started = (TestThread.ThreadState == ThreadState.Running);
260                         Assert.AreEqual (started, test1.run, "#15 Thread Is not in the correct state: ");
261                         TestThread.Abort();
262                 }
263                 }
264
265                 public void TestApartment()
266                 {
267                         C2Test test1 = new C2Test();
268                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
269                         ApartmentState before = TestThread.ApartmentState;
270                         TestThread.Start();
271                         TestUtil.WaitForAlive (TestThread, "wait5");
272                         ApartmentState after = TestThread.ApartmentState;
273                         TestThread.Abort();
274                         Assert.AreEqual (before, after, "#21 Apartment State Changed when not needed");
275                 }
276
277                 [Category("NotDotNet")]
278                 public void TestApartmentState()
279                 {
280                         C2Test test1 = new C2Test();
281                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
282                         ApartmentState before = TestThread.ApartmentState;
283                         TestThread.Start();
284                         TestUtil.WaitForAlive (TestThread, "wait6");
285                         ApartmentState after = TestThread.ApartmentState;
286                         TestThread.Abort();
287                         Assert.AreEqual (before, after, "#31 Apartment State Changed when not needed: ");
288                 }
289
290                 public void TestPriority1()
291                 {
292                         C2Test test1 = new C2Test();
293                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
294                         try {
295                                 TestThread.Priority=ThreadPriority.BelowNormal;
296                                 ThreadPriority after = TestThread.Priority;
297                                 TestThread.Start();
298                                 TestUtil.WaitForAlive (TestThread, "wait7");
299                                 ThreadPriority before = TestThread.Priority;
300                                 Assert.AreEqual (before, after, "#41 Unexpected Priority Change: ");
301                         }
302                         finally {
303                                 TestThread.Abort();
304                         }
305                 }
306
307                 [Test]
308                 public void AbortUnstarted ()
309                 {
310                         C2Test test1 = new C2Test();
311                         Thread th = new Thread (new ThreadStart (test1.TestMethod));
312                         th.Abort ();
313                         th.Start ();
314                 }
315
316                 [Category("NotWorking")] // this is a MonoTODO -> no support for Priority
317                 public void TestPriority2()
318                 {
319                         C2Test test1 = new C2Test();
320                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
321                         try {
322                                 Assert.AreEqual (ThreadPriority.Normal, TestThread.Priority, "#42 Incorrect Priority in New thread: ");
323                                 TestThread.Start();
324                                 TestUtil.WaitForAliveOrStop (TestThread, "wait8");
325                                 Assert.AreEqual (ThreadPriority.Normal, TestThread.Priority, "#43 Incorrect Priority in Started thread: ");
326                         }
327                         finally {
328                                 TestThread.Abort();
329                         }
330                         Assert.AreEqual (ThreadPriority.Normal, TestThread.Priority, "#44 Incorrect Priority in Aborted thread: ");
331                 }
332
333                 [Category("NotWorking")] // this is a MonoTODO -> no support for Priority
334                 public void TestPriority3()
335                 {
336                         C2Test test1 = new C2Test();
337                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
338                         try {
339                                 TestThread.Start();
340                                 TestThread.Priority = ThreadPriority.Lowest;
341                                 Assert.AreEqual (ThreadPriority.Lowest, TestThread.Priority, "#45A Incorrect Priority:");
342                                 TestThread.Priority = ThreadPriority.BelowNormal;
343                                 Assert.AreEqual (ThreadPriority.BelowNormal, TestThread.Priority, "#45B Incorrect Priority:");
344                                 TestThread.Priority = ThreadPriority.Normal;
345                                 Assert.AreEqual (ThreadPriority.Normal, TestThread.Priority, "#45C Incorrect Priority:");
346                                 TestThread.Priority = ThreadPriority.AboveNormal;
347                                 Assert.AreEqual (ThreadPriority.AboveNormal, TestThread.Priority, "#45D Incorrect Priority:");
348                                 TestThread.Priority = ThreadPriority.Highest;
349                                 Assert.AreEqual (ThreadPriority.Highest, TestThread.Priority, "#45E Incorrect Priority:");
350                         }
351                         finally {
352                                 TestThread.Abort();
353                         }
354                 }
355
356
357                 public void TestIsBackground1()
358                 {
359                         C2Test test1 = new C2Test();
360                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
361                         try {
362                                 TestThread.Start();
363                                 TestUtil.WaitForAlive (TestThread, "wait9");
364                                 bool state = TestThread.IsBackground;
365                                 Assert.IsFalse (state, "#51 IsBackground not set at the default state: ");
366                         }
367                         finally {
368                                 TestThread.Abort();
369                         }
370                 }
371
372                 public void TestIsBackground2()
373                 {
374                         C2Test test1 = new C2Test();
375                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
376                         TestThread.IsBackground = true;
377                         try {
378                                 TestThread.Start();
379                         }
380                         finally {
381                                 TestThread.Abort();
382                         }
383                         Assert.IsTrue (TestThread.IsBackground, "#52 Is Background Changed ot Start ");
384                 }
385
386
387                 public void TestName()
388                 {
389                         C2Test test1 = new C2Test();
390                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
391                         try {
392                                 TestThread.Start();
393                                 TestUtil.WaitForAlive (TestThread, "wait10");
394                                 string name = TestThread.Name;
395                                 Assert.IsNull (name, "#61 Name set when mustn't be set: ");
396                                 string newname = "Testing....";
397                                 TestThread.Name = newname;
398                                 Assert.AreEqual (newname, TestThread.Name, "#62 Name not set when must be set: ");
399                         }
400                         finally {
401                                 TestThread.Abort();
402                         }
403                 }
404
405                 [Category("NotDotNet")]
406                 public void TestNestedThreads1()
407                 {
408                         C3Test  test1 = new C3Test();
409                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod1));
410                         try {
411                                 TestThread.Start();
412                                 TestUtil.WaitForAlive (TestThread, "wait11");
413                         }
414                         catch(Exception e) {
415                                 Assert.Fail ("#71 Unexpected Exception" + e.Message);
416                         }
417                         finally {
418                                 TestThread.Abort();
419                         }
420                 }
421
422                 public void TestNestedThreads2()
423                 {
424                         C4Test test1 = new C4Test();
425                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod1));
426                         try {
427                                 TestThread.Start();
428                         }
429                         catch(Exception e) {
430                                 Assert.Fail ("#81 Unexpected Exception" + e.ToString());
431                         }
432                         finally {
433                                 TestThread.Abort();
434                         }
435                 }
436
437                 
438                 public void TestJoin1()
439                 {
440                         C1Test test1 = new C1Test();
441                         C1Test test2 = new C1Test();
442                         Thread thread1 = new Thread(new ThreadStart(test1.TestMethod));
443                         Thread thread2 = new Thread(new ThreadStart(test1.TestMethod2));
444                         try
445                         {
446                                 thread1.Start();
447                                 thread2.Start();
448                                 thread2.Join();
449                         }
450                         catch(Exception e)
451                         {
452                                 Assert.Fail ("#91 Unexpected Exception " + e.ToString());
453                         }
454                         finally
455                         {
456                                 thread1.Abort();
457                                 thread2.Abort();
458                         }
459                 }
460                 
461                 public void TestThreadState()
462                 {
463                         //TODO: Test The rest of the possible transitions
464                         C2Test test1 = new C2Test();
465                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
466                         Assert.AreEqual (ThreadState.Unstarted, TestThread.ThreadState, "#101 Wrong Thread State");
467                         try {
468                                 TestThread.Start();
469                                 //while(!TestThread.IsAlive); //In the MS Documentation this is not necessary
470                                                                                           //but in the MS SDK it is
471                                 Assert.IsTrue (TestThread.ThreadState == ThreadState.Running || (TestThread.ThreadState & ThreadState.Unstarted) != 0,
472                                         "#102 Wrong Thread State: " + TestThread.ThreadState.ToString ());
473                         }
474                         finally {
475                                 TestThread.Abort();
476                         }
477                         
478                         TestUtil.WaitForNotAlive (TestThread, "wait12");
479                         // Docs say state will be Stopped, but Aborted happens sometimes (?)
480                         Assert.IsTrue ((ThreadState.Stopped & TestThread.ThreadState) != 0 || (ThreadState.Aborted & TestThread.ThreadState) != 0,
481                                 "#103 Wrong Thread State: " + TestThread.ThreadState.ToString ());
482                 } 
483
484                 [Test]
485                 [Ignore ("see comment below.")]
486                 public void CurrentPrincipal_PrincipalPolicy_NoPrincipal () 
487                 {
488                         // note: switching from PrincipalPolicy won't work inside the same thread
489                         // because as soon as a Principal object is created the Policy doesn't matter anymore
490                         Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.NoPrincipal));
491                         try {
492                                 t.Start ();
493                                 t.Join ();
494                         }
495                         catch {
496                                 t.Abort ();
497                         }
498                 }
499
500 #if !TARGET_JVM // AppDomain.SetPrincipalPolicy not supported for TARGET_JVM
501                 [Test]
502                 [Ignore ("see comment below.")]
503                 public void CurrentPrincipal_PrincipalPolicy_UnauthenticatedPrincipal () 
504                 {
505                         // note: switching from PrincipalPolicy won't work inside the same thread
506                         // because as soon as a Principal object is created the Policy doesn't matter anymore
507                         Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.UnauthenticatedPrincipal));
508                         try {
509                                 t.Start ();
510                                 t.Join ();
511                         }
512                         catch {
513                                 t.Abort ();
514                         }
515                 }
516
517                 [Test]
518                 public void CurrentPrincipal_PrincipalPolicy_WindowsPrincipal () 
519                 {
520                         // note: switching from PrincipalPolicy won't work inside the same thread
521                         // because as soon as a Principal object is created the Policy doesn't matter anymore
522                         Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.WindowsPrincipal));
523                         try {
524                                 t.Start ();
525                                 t.Join ();
526                         }
527                         catch {
528                                 t.Abort ();
529                         }
530                 }
531 #endif // TARGET_JVM
532                 
533                 [Test]
534                 public void IPrincipal_CopyOnNewThread () 
535                 {
536                         Thread.CurrentPrincipal = new GenericPrincipal (new GenericIdentity ("bad"), null);
537                         Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.CopyOnNewThread));
538                         try {
539                                 Thread.CurrentPrincipal = new GenericPrincipal (new GenericIdentity ("good"), null);
540                                 t.Start ();
541                                 t.Join ();
542                         }
543                         catch {
544                                 t.Abort ();
545                         }
546                 }
547
548                 int counter = 0;
549                 
550                 [Category("NotDotNet")]
551                 public void TestSuspend ()
552                 {
553                         Thread t = new Thread (new ThreadStart (DoCount));
554                         t.IsBackground = true;
555                         t.Start ();
556                         
557                         CheckIsRunning ("t1", t);
558                         
559                         t.Suspend ();
560                         WaitSuspended ("t2", t);
561                         
562                         CheckIsNotRunning ("t3", t);
563                         
564                         t.Resume ();
565                         WaitResumed ("t4", t);
566                         
567                         CheckIsRunning ("t5", t);
568                         
569                         t.Abort ();
570                         TestUtil.WaitForNotAlive (t, "wait13");
571                         CheckIsNotRunning ("t6", t);
572                 }
573                 
574                 [Category("NotDotNet")]
575                 [Category("NotWorking")]
576                 public void TestSuspendAbort ()
577                 {
578                         Thread t = new Thread (new ThreadStart (DoCount));
579                         t.IsBackground = true;
580                         t.Start ();
581                         
582                         CheckIsRunning ("t1", t);
583                         
584                         t.Suspend ();
585                         WaitSuspended ("t2", t);
586                         
587                         CheckIsNotRunning ("t3", t);
588                         
589                         t.Abort ();
590                         
591                         int n=0;
592                         while (t.IsAlive && n < 200) {
593                                 Thread.Sleep (10);
594                                 n++;
595                         }
596
597                         Assert.IsTrue (n < 200, "Timeout while waiting for abort");
598                         
599                         CheckIsNotRunning ("t6", t);
600                 }               
601                 
602                 void CheckIsRunning (string s, Thread t)
603                 {
604                         int c = counter;
605                         Thread.Sleep (100);
606                         Assert.IsTrue (counter > c, s);
607                 }
608                 
609                 void CheckIsNotRunning (string s, Thread t)
610                 {
611                         int c = counter;
612                         Thread.Sleep (100);
613                         Assert.AreEqual (counter, c, s);
614                 }
615                 
616                 void WaitSuspended (string s, Thread t)
617                 {
618                         int n=0;
619                         ThreadState state = t.ThreadState;
620                         while ((state & ThreadState.Suspended) == 0) {
621                                 Assert.IsTrue ((state & ThreadState.SuspendRequested) != 0, s + ": expected SuspendRequested state");
622                                 Thread.Sleep (10);
623                                 n++;
624                                 Assert.IsTrue (n < 100, s + ": failed to suspend");
625                                 state = t.ThreadState;
626                         }
627                         Assert.IsTrue ((state & ThreadState.SuspendRequested) == 0, s + ": SuspendRequested state not expected");
628                 }
629                 
630                 void WaitResumed (string s, Thread t)
631                 {
632                         int n=0;
633                         while ((t.ThreadState & ThreadState.Suspended) != 0) {
634                                 Thread.Sleep (10);
635                                 n++;
636                                 Assert.IsTrue (n < 100, s + ": failed to resume");
637                         }
638                 }
639                 
640                 public void DoCount ()
641                 {
642                         while (true) {
643                                 counter++;
644                                 Thread.Sleep (1);
645                         }
646                 }
647         }
648
649         [TestFixture]
650         public class ThreadApartmentTest
651         {
652                 void Start ()
653                 {
654                 }
655
656                 [Test] // bug #81658
657                 [Category ("NotWorking")]
658                 public void ApartmentState_StoppedThread ()
659                 {
660                         Thread t1 = new Thread (new ThreadStart (Start));
661                         t1.Start ();
662                         t1.Join ();
663                         Assert.AreEqual (ThreadState.Stopped, t1.ThreadState, "#1");
664                         try {
665                                 ApartmentState state = t1.ApartmentState;
666                                 Assert.Fail ("#2");
667                         } catch (ThreadStateException) {
668                         }
669                 }
670
671                 [Test]
672                 public void TestApartmentState ()
673                 {
674                         Thread t1 = new Thread (new ThreadStart (Start));
675                         Thread t2 = new Thread (new ThreadStart (Start));
676                         Thread t3 = new Thread (new ThreadStart (Start));
677
678                         Assert.AreEqual (ApartmentState.Unknown, t1.ApartmentState, "Thread1 Default");
679                         Assert.AreEqual (ApartmentState.Unknown, t2.ApartmentState, "Thread2 Default");
680                         Assert.AreEqual (ApartmentState.Unknown, t3.ApartmentState, "Thread3 Default");
681
682                         t1.ApartmentState = ApartmentState.STA;
683                         Assert.AreEqual (ApartmentState.STA, t1.ApartmentState, "Thread1 Set Once");
684                         t1.ApartmentState = ApartmentState.MTA;
685                         Assert.AreEqual (ApartmentState.STA, t1.ApartmentState, "Thread1 Set Twice");
686
687                         t2.ApartmentState = ApartmentState.MTA;
688                         Assert.AreEqual (ApartmentState.MTA, t2.ApartmentState, "Thread2 Set Once");
689                         t2.ApartmentState = ApartmentState.STA;
690                         Assert.AreEqual (ApartmentState.MTA, t2.ApartmentState, "Thread2 Set Twice");
691
692                         bool exception_occured = false;
693                         try {
694                                 t3.ApartmentState = ApartmentState.Unknown;
695                         }
696                         catch (Exception) {
697                                 exception_occured = true;
698                         }
699                         Assert.AreEqual (ApartmentState.Unknown, t3.ApartmentState, "Thread3 Set Invalid");
700 #if NET_2_0
701                         Assert.IsFalse (exception_occured, "Thread3 Set Invalid Exception Occured");
702 #else
703                         Assert.IsTrue (exception_occured, "Thread3 Set Invalid Exception Occured");
704 #endif
705
706                         t1.Start ();
707                         exception_occured = false;
708                         try {
709                                 t1.ApartmentState = ApartmentState.STA;
710                         }
711                         catch (Exception) {
712                                 exception_occured = true;
713                         }
714                         Assert.IsTrue (exception_occured, "Thread1 Started Invalid Exception Occured");
715                 }
716         }
717         
718         public class TestUtil
719         {
720                 public static void WaitForNotAlive (Thread t, string s)
721                 {
722                         WhileAlive (t, true, s);
723                 }
724                 
725                 public static void WaitForAlive (Thread t, string s)
726                 {
727                         WhileAlive (t, false, s);
728                 }
729                 
730                 public static bool WaitForAliveOrStop (Thread t, string s)
731                 {
732                         return WhileAliveOrStop (t, false, s);
733                 }
734                 
735                 public static void WhileAlive (Thread t, bool alive, string s)
736                 {
737                         DateTime ti = DateTime.Now;
738                         while (t.IsAlive == alive) {
739                                 if ((DateTime.Now - ti).TotalSeconds > 10) {
740                                         if (alive) Assert.Fail ("Timeout while waiting for not alive state. " + s);
741                                         else Assert.Fail ("Timeout while waiting for alive state. " + s);
742                                 }
743                         }
744                 }
745
746                 public static bool WhileAliveOrStop (Thread t, bool alive, string s)
747                 {
748                         DateTime ti = DateTime.Now;
749                         while (t.IsAlive == alive) {
750                                 if (t.ThreadState == ThreadState.Stopped)
751                                         return false;
752
753                                 if ((DateTime.Now - ti).TotalSeconds > 10) {
754                                         if (alive) Assert.Fail ("Timeout while waiting for not alive state. " + s);
755                                         else Assert.Fail ("Timeout while waiting for alive state. " + s);
756                                 }
757                         }
758
759                         return true;
760                 }
761         }
762 }