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