eddef0f59aefb94e9ad7a20221c2f8770299b3f3
[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                 public void TestIsBackground1()
357                 {
358                         C2Test test1 = new C2Test();
359                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
360                         try {
361                                 TestThread.Start();
362                                 TestUtil.WaitForAlive (TestThread, "wait9");
363                                 bool state = TestThread.IsBackground;
364                                 Assert.IsFalse (state, "#51 IsBackground not set at the default state: ");
365                         }
366                         finally {
367                                 TestThread.Abort();
368                         }
369                 }
370
371                 public void TestIsBackground2()
372                 {
373                         C2Test test1 = new C2Test();
374                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
375                         TestThread.IsBackground = true;
376                         try {
377                                 TestThread.Start();
378                         }
379                         finally {
380                                 TestThread.Abort();
381                         }
382                         Assert.IsTrue (TestThread.IsBackground, "#52 Is Background Changed ot Start ");
383                 }
384
385
386                 public void TestName()
387                 {
388                         C2Test test1 = new C2Test();
389                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
390                         try {
391                                 TestThread.Start();
392                                 TestUtil.WaitForAlive (TestThread, "wait10");
393                                 string name = TestThread.Name;
394                                 Assert.IsNull (name, "#61 Name set when mustn't be set: ");
395                                 string newname = "Testing....";
396                                 TestThread.Name = newname;
397                                 Assert.AreEqual (newname, TestThread.Name, "#62 Name not set when must be set: ");
398                         }
399                         finally {
400                                 TestThread.Abort();
401                         }
402                 }
403
404                 [Category("NotDotNet")]
405                 public void TestNestedThreads1()
406                 {
407                         C3Test  test1 = new C3Test();
408                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod1));
409                         try {
410                                 TestThread.Start();
411                                 TestUtil.WaitForAlive (TestThread, "wait11");
412                         }
413                         catch(Exception e) {
414                                 Assert.Fail ("#71 Unexpected Exception" + e.Message);
415                         }
416                         finally {
417                                 TestThread.Abort();
418                         }
419                 }
420
421                 public void TestNestedThreads2()
422                 {
423                         C4Test test1 = new C4Test();
424                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod1));
425                         try {
426                                 TestThread.Start();
427                         }
428                         catch(Exception e) {
429                                 Assert.Fail ("#81 Unexpected Exception" + e.ToString());
430                         }
431                         finally {
432                                 TestThread.Abort();
433                         }
434                 }
435
436                 
437                 public void TestJoin1()
438                 {
439                         C1Test test1 = new C1Test();
440                         C1Test test2 = new C1Test();
441                         Thread thread1 = new Thread(new ThreadStart(test1.TestMethod));
442                         Thread thread2 = new Thread(new ThreadStart(test1.TestMethod2));
443                         try
444                         {
445                                 thread1.Start();
446                                 thread2.Start();
447                                 thread2.Join();
448                         }
449                         catch(Exception e)
450                         {
451                                 Assert.Fail ("#91 Unexpected Exception " + e.ToString());
452                         }
453                         finally
454                         {
455                                 thread1.Abort();
456                                 thread2.Abort();
457                         }
458                 }
459                 
460                 public void TestThreadState()
461                 {
462                         //TODO: Test The rest of the possible transitions
463                         C2Test test1 = new C2Test();
464                         Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
465                         Assert.AreEqual (ThreadState.Unstarted, TestThread.ThreadState, "#101 Wrong Thread State");
466                         try {
467                                 TestThread.Start();
468                                 //while(!TestThread.IsAlive); //In the MS Documentation this is not necessary
469                                                                                           //but in the MS SDK it is
470                                 Assert.IsTrue (TestThread.ThreadState == ThreadState.Running || (TestThread.ThreadState & ThreadState.Unstarted) != 0,
471                                         "#102 Wrong Thread State: " + TestThread.ThreadState.ToString ());
472                         }
473                         finally {
474                                 TestThread.Abort();
475                         }
476                         
477                         TestUtil.WaitForNotAlive (TestThread, "wait12");
478                         // Docs say state will be Stopped, but Aborted happens sometimes (?)
479                         Assert.IsTrue ((ThreadState.Stopped & TestThread.ThreadState) != 0 || (ThreadState.Aborted & TestThread.ThreadState) != 0,
480                                 "#103 Wrong Thread State: " + TestThread.ThreadState.ToString ());
481                 } 
482
483                 [Test]
484                 [Ignore ("see comment below.")]
485                 public void CurrentPrincipal_PrincipalPolicy_NoPrincipal () 
486                 {
487                         // note: switching from PrincipalPolicy won't work inside the same thread
488                         // because as soon as a Principal object is created the Policy doesn't matter anymore
489                         Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.NoPrincipal));
490                         try {
491                                 t.Start ();
492                                 t.Join ();
493                         }
494                         catch {
495                                 t.Abort ();
496                         }
497                 }
498
499 #if !TARGET_JVM // AppDomain.SetPrincipalPolicy not supported for TARGET_JVM
500                 [Test]
501                 [Ignore ("see comment below.")]
502                 public void CurrentPrincipal_PrincipalPolicy_UnauthenticatedPrincipal () 
503                 {
504                         // note: switching from PrincipalPolicy won't work inside the same thread
505                         // because as soon as a Principal object is created the Policy doesn't matter anymore
506                         Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.UnauthenticatedPrincipal));
507                         try {
508                                 t.Start ();
509                                 t.Join ();
510                         }
511                         catch {
512                                 t.Abort ();
513                         }
514                 }
515
516                 [Test]
517                 public void CurrentPrincipal_PrincipalPolicy_WindowsPrincipal () 
518                 {
519                         // note: switching from PrincipalPolicy won't work inside the same thread
520                         // because as soon as a Principal object is created the Policy doesn't matter anymore
521                         Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.WindowsPrincipal));
522                         try {
523                                 t.Start ();
524                                 t.Join ();
525                         }
526                         catch {
527                                 t.Abort ();
528                         }
529                 }
530 #endif // TARGET_JVM
531                 
532                 [Test]
533                 public void IPrincipal_CopyOnNewThread () 
534                 {
535                         Thread.CurrentPrincipal = new GenericPrincipal (new GenericIdentity ("bad"), null);
536                         Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.CopyOnNewThread));
537                         try {
538                                 Thread.CurrentPrincipal = new GenericPrincipal (new GenericIdentity ("good"), null);
539                                 t.Start ();
540                                 t.Join ();
541                         }
542                         catch {
543                                 t.Abort ();
544                         }
545                 }
546
547                 int counter = 0;
548                 
549                 [Category("NotDotNet")]
550                 public void TestSuspend ()
551                 {
552                         Thread t = new Thread (new ThreadStart (DoCount));
553                         t.IsBackground = true;
554                         t.Start ();
555                         
556                         CheckIsRunning ("t1", t);
557                         
558                         t.Suspend ();
559                         WaitSuspended ("t2", t);
560                         
561                         CheckIsNotRunning ("t3", t);
562                         
563                         t.Resume ();
564                         WaitResumed ("t4", t);
565                         
566                         CheckIsRunning ("t5", t);
567                         
568                         t.Abort ();
569                         TestUtil.WaitForNotAlive (t, "wait13");
570                         CheckIsNotRunning ("t6", t);
571                 }
572                 
573                 [Category("NotDotNet")]
574                 [Category("NotWorking")]
575                 public void TestSuspendAbort ()
576                 {
577                         Thread t = new Thread (new ThreadStart (DoCount));
578                         t.IsBackground = true;
579                         t.Start ();
580                         
581                         CheckIsRunning ("t1", t);
582                         
583                         t.Suspend ();
584                         WaitSuspended ("t2", t);
585                         
586                         CheckIsNotRunning ("t3", t);
587                         
588                         t.Abort ();
589                         
590                         int n=0;
591                         while (t.IsAlive && n < 200) {
592                                 Thread.Sleep (10);
593                                 n++;
594                         }
595
596                         Assert.IsTrue (n < 200, "Timeout while waiting for abort");
597                         
598                         CheckIsNotRunning ("t6", t);
599                 }               
600                 
601                 void CheckIsRunning (string s, Thread t)
602                 {
603                         int c = counter;
604                         Thread.Sleep (100);
605                         Assert.IsTrue (counter > c, s);
606                 }
607                 
608                 void CheckIsNotRunning (string s, Thread t)
609                 {
610                         int c = counter;
611                         Thread.Sleep (100);
612                         Assert.AreEqual (counter, c, s);
613                 }
614                 
615                 void WaitSuspended (string s, Thread t)
616                 {
617                         int n=0;
618                         ThreadState state = t.ThreadState;
619                         while ((state & ThreadState.Suspended) == 0) {
620                                 Assert.IsTrue ((state & ThreadState.SuspendRequested) != 0, s + ": expected SuspendRequested state");
621                                 Thread.Sleep (10);
622                                 n++;
623                                 Assert.IsTrue (n < 100, s + ": failed to suspend");
624                                 state = t.ThreadState;
625                         }
626                         Assert.IsTrue ((state & ThreadState.SuspendRequested) == 0, s + ": SuspendRequested state not expected");
627                 }
628                 
629                 void WaitResumed (string s, Thread t)
630                 {
631                         int n=0;
632                         while ((t.ThreadState & ThreadState.Suspended) != 0) {
633                                 Thread.Sleep (10);
634                                 n++;
635                                 Assert.IsTrue (n < 100, s + ": failed to resume");
636                         }
637                 }
638                 
639                 public void DoCount ()
640                 {
641                         while (true) {
642                                 counter++;
643                                 Thread.Sleep (1);
644                         }
645                 }
646         }
647
648         [TestFixture]
649         public class ThreadStateTest {
650                 void Start ()
651                 {
652                 }
653
654                 [Test] // bug #81720
655                 public void IsBackGround ()
656                 {
657                         Thread t1 = new Thread (new ThreadStart (Start));
658                         Assert.AreEqual (ThreadState.Unstarted, t1.ThreadState, "#A1");
659                         Assert.IsFalse (t1.IsBackground, "#A2");
660                         t1.Start ();
661                         t1.Join ();
662                         Assert.AreEqual (ThreadState.Stopped, t1.ThreadState, "#A3");
663
664                         // uncomment when bug #81658 is fixed
665                         /*
666                         try {
667                                 bool isBackGround = t1.IsBackground;
668                                 Assert.Fail ("#A4: " + isBackGround.ToString ());
669                         } catch (ThreadStateException ex) {
670                                 Assert.AreEqual (typeof (ThreadStateException), ex.GetType (), "#A5");
671                                 Assert.IsNull (ex.InnerException, "#A6");
672                                 Assert.IsNotNull (ex.Message, "#A7");
673                         }
674                         */
675
676                         Thread t2 = new Thread (new ThreadStart (Start));
677                         Assert.AreEqual (ThreadState.Unstarted, t2.ThreadState, "#B1");
678                         t2.IsBackground = true;
679                         Assert.AreEqual (ThreadState.Unstarted | ThreadState.Background, t2.ThreadState, "#B2");
680                         Assert.IsTrue (t2.IsBackground, "#B3");
681                         t2.Start ();
682                         t2.Join ();
683                         Assert.AreEqual (ThreadState.Stopped, t2.ThreadState, "#B4");
684                         // uncomment when bug #81658 is fixed
685                         /*
686                         try {
687                                 bool isBackGround = t2.IsBackground;
688                                 Assert.Fail ("#B5: " + isBackGround.ToString ());
689                         } catch (ThreadStateException ex) {
690                                 Assert.AreEqual (typeof (ThreadStateException), ex.GetType (), "#B6");
691                                 Assert.IsNull (ex.InnerException, "#B7");
692                                 Assert.IsNotNull (ex.Message, "#B8");
693                         }
694                         */
695                 }
696         }
697
698         [TestFixture]
699         public class ThreadApartmentTest
700         {
701                 void Start ()
702                 {
703                 }
704
705                 [Test] // bug #81658
706                 [Category ("NotWorking")]
707                 public void ApartmentState_StoppedThread ()
708                 {
709                         Thread t1 = new Thread (new ThreadStart (Start));
710                         t1.Start ();
711                         t1.Join ();
712                         try {
713                                 ApartmentState state = t1.ApartmentState;
714                                 Assert.Fail ("#A1: " + state.ToString ());
715                         } catch (ThreadStateException ex) {
716                                 Assert.AreEqual (typeof (ThreadStateException), ex.GetType (), "#A2");
717                                 Assert.IsNull (ex.InnerException, "#A3");
718                                 Assert.IsNotNull (ex.Message, "#A4");
719                         }
720
721                         Thread t2 = new Thread (new ThreadStart (Start));
722                         t2.IsBackground = true;
723                         t2.Start ();
724                         t2.Join ();
725                         try {
726                                 ApartmentState state = t2.ApartmentState;
727                                 Assert.Fail ("#B1: " + state.ToString ());
728                         } catch (ThreadStateException ex) {
729                                 Assert.AreEqual (typeof (ThreadStateException), ex.GetType (), "#B2");
730                                 Assert.IsNull (ex.InnerException, "#B3");
731                                 Assert.IsNotNull (ex.Message, "#B4");
732                         }
733                 }
734
735                 [Test]
736                 public void ApartmentState_BackGround ()
737                 {
738                         Thread t1 = new Thread (new ThreadStart (Start));
739                         t1.IsBackground = true;
740                         Assert.AreEqual (ApartmentState.Unknown, t1.ApartmentState, "#1");
741                         t1.ApartmentState = ApartmentState.STA;
742                         Assert.AreEqual (ApartmentState.STA, t1.ApartmentState, "#2");
743                 }
744
745                 [Test]
746                 public void TestApartmentState ()
747                 {
748                         Thread t1 = new Thread (new ThreadStart (Start));
749                         Thread t2 = new Thread (new ThreadStart (Start));
750                         Thread t3 = new Thread (new ThreadStart (Start));
751
752                         Assert.AreEqual (ApartmentState.Unknown, t1.ApartmentState, "Thread1 Default");
753                         Assert.AreEqual (ApartmentState.Unknown, t2.ApartmentState, "Thread2 Default");
754                         Assert.AreEqual (ApartmentState.Unknown, t3.ApartmentState, "Thread3 Default");
755
756                         t1.ApartmentState = ApartmentState.STA;
757                         Assert.AreEqual (ApartmentState.STA, t1.ApartmentState, "Thread1 Set Once");
758                         t1.ApartmentState = ApartmentState.MTA;
759                         Assert.AreEqual (ApartmentState.STA, t1.ApartmentState, "Thread1 Set Twice");
760
761                         t2.ApartmentState = ApartmentState.MTA;
762                         Assert.AreEqual (ApartmentState.MTA, t2.ApartmentState, "Thread2 Set Once");
763                         t2.ApartmentState = ApartmentState.STA;
764                         Assert.AreEqual (ApartmentState.MTA, t2.ApartmentState, "Thread2 Set Twice");
765
766                         bool exception_occured = false;
767                         try {
768                                 t3.ApartmentState = ApartmentState.Unknown;
769                         }
770                         catch (Exception) {
771                                 exception_occured = true;
772                         }
773                         Assert.AreEqual (ApartmentState.Unknown, t3.ApartmentState, "Thread3 Set Invalid");
774 #if NET_2_0
775                         Assert.IsFalse (exception_occured, "Thread3 Set Invalid Exception Occured");
776 #else
777                         Assert.IsTrue (exception_occured, "Thread3 Set Invalid Exception Occured");
778 #endif
779
780                         t1.Start ();
781                         exception_occured = false;
782                         try {
783                                 t1.ApartmentState = ApartmentState.STA;
784                         }
785                         catch (Exception) {
786                                 exception_occured = true;
787                         }
788                         Assert.IsTrue (exception_occured, "Thread1 Started Invalid Exception Occured");
789                 }
790         }
791         
792         public class TestUtil
793         {
794                 public static void WaitForNotAlive (Thread t, string s)
795                 {
796                         WhileAlive (t, true, s);
797                 }
798                 
799                 public static void WaitForAlive (Thread t, string s)
800                 {
801                         WhileAlive (t, false, s);
802                 }
803                 
804                 public static bool WaitForAliveOrStop (Thread t, string s)
805                 {
806                         return WhileAliveOrStop (t, false, s);
807                 }
808                 
809                 public static void WhileAlive (Thread t, bool alive, string s)
810                 {
811                         DateTime ti = DateTime.Now;
812                         while (t.IsAlive == alive) {
813                                 if ((DateTime.Now - ti).TotalSeconds > 10) {
814                                         if (alive) Assert.Fail ("Timeout while waiting for not alive state. " + s);
815                                         else Assert.Fail ("Timeout while waiting for alive state. " + s);
816                                 }
817                         }
818                 }
819
820                 public static bool WhileAliveOrStop (Thread t, bool alive, string s)
821                 {
822                         DateTime ti = DateTime.Now;
823                         while (t.IsAlive == alive) {
824                                 if (t.ThreadState == ThreadState.Stopped)
825                                         return false;
826
827                                 if ((DateTime.Now - ti).TotalSeconds > 10) {
828                                         if (alive) Assert.Fail ("Timeout while waiting for not alive state. " + s);
829                                         else Assert.Fail ("Timeout while waiting for alive state. " + s);
830                                 }
831                         }
832
833                         return true;
834                 }
835         }
836 }