New test.
[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                 [Ignore ("see comment below.")]
480                 public void CurrentPrincipal_PrincipalPolicy_NoPrincipal () 
481                 {
482                         // note: switching from PrincipalPolicy won't work inside the same thread
483                         // because as soon as a Principal object is created the Policy doesn't matter anymore
484                         Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.NoPrincipal));
485                         try {
486                                 t.Start ();
487                                 t.Join ();
488                         }
489                         catch {
490                                 t.Abort ();
491                         }
492                 }
493
494                 [Test]
495                 [Ignore ("see comment below.")]
496                 public void CurrentPrincipal_PrincipalPolicy_UnauthenticatedPrincipal () 
497                 {
498                         // note: switching from PrincipalPolicy won't work inside the same thread
499                         // because as soon as a Principal object is created the Policy doesn't matter anymore
500                         Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.UnauthenticatedPrincipal));
501                         try {
502                                 t.Start ();
503                                 t.Join ();
504                         }
505                         catch {
506                                 t.Abort ();
507                         }
508                 }
509
510                 [Test]
511                 public void CurrentPrincipal_PrincipalPolicy_WindowsPrincipal () 
512                 {
513                         // note: switching from PrincipalPolicy won't work inside the same thread
514                         // because as soon as a Principal object is created the Policy doesn't matter anymore
515                         Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.WindowsPrincipal));
516                         try {
517                                 t.Start ();
518                                 t.Join ();
519                         }
520                         catch {
521                                 t.Abort ();
522                         }
523                 }
524                 
525                 [Test]
526                 public void IPrincipal_CopyOnNewThread () 
527                 {
528                         Thread.CurrentPrincipal = new GenericPrincipal (new GenericIdentity ("bad"), null);
529                         Thread t = new Thread (new ThreadStart (ThreadedPrincipalTest.CopyOnNewThread));
530                         try {
531                                 Thread.CurrentPrincipal = new GenericPrincipal (new GenericIdentity ("good"), null);
532                                 t.Start ();
533                                 t.Join ();
534                         }
535                         catch {
536                                 t.Abort ();
537                         }
538                 }
539
540                 int counter = 0;
541                 
542                 [Category("NotDotNet")]
543                 public void TestSuspend ()
544                 {
545                         Thread t = new Thread (new ThreadStart (DoCount));
546                         t.IsBackground = true;
547                         t.Start ();
548                         
549                         CheckIsRunning ("t1", t);
550                         
551                         t.Suspend ();
552                         WaitSuspended ("t2", t);
553                         
554                         CheckIsNotRunning ("t3", t);
555                         
556                         t.Resume ();
557                         WaitResumed ("t4", t);
558                         
559                         CheckIsRunning ("t5", t);
560                         
561                         t.Abort ();
562                         TestUtil.WaitForNotAlive (t, "wait13");
563                         CheckIsNotRunning ("t6", t);
564                 }
565                 
566                 [Category("NotDotNet")]
567                 [Category("NotWorking")]
568                 public void TestSuspendAbort ()
569                 {
570                         Thread t = new Thread (new ThreadStart (DoCount));
571                         t.IsBackground = true;
572                         t.Start ();
573                         
574                         CheckIsRunning ("t1", t);
575                         
576                         t.Suspend ();
577                         WaitSuspended ("t2", t);
578                         
579                         CheckIsNotRunning ("t3", t);
580                         
581                         t.Abort ();
582                         
583                         int n=0;
584                         while (t.IsAlive && n < 200) {
585                                 Thread.Sleep (10);
586                                 n++;
587                         }
588                         
589                         Assert ("Timeout while waiting for abort", n < 200);
590                         
591                         CheckIsNotRunning ("t6", t);
592                 }               
593                 
594                 void CheckIsRunning (string s, Thread t)
595                 {
596                         int c = counter;
597                         Thread.Sleep (100);
598                         Assert (s, counter > c);
599                 }
600                 
601                 void CheckIsNotRunning (string s, Thread t)
602                 {
603                         int c = counter;
604                         Thread.Sleep (100);
605                         Assert (s, counter == c);
606                 }
607                 
608                 void WaitSuspended (string s, Thread t)
609                 {
610                         int n=0;
611                         ThreadState state = t.ThreadState;
612                         while ((state & ThreadState.Suspended) == 0) {
613                                 Assert (s + ": expected SuspendRequested state", (state & ThreadState.SuspendRequested) != 0);
614                                 Thread.Sleep (10);
615                                 n++;
616                                 Assert (s + ": failed to suspend", n < 100);
617                                 state = t.ThreadState;
618                         }
619                         Assert (s + ": SuspendRequested state not expected", (state & ThreadState.SuspendRequested) == 0);
620                 }
621                 
622                 void WaitResumed (string s, Thread t)
623                 {
624                         int n=0;
625                         while ((t.ThreadState & ThreadState.Suspended) != 0) {
626                                 Thread.Sleep (10);
627                                 n++;
628                                 Assert (s + ": failed to resume", n < 100);
629                         }
630                 }
631                 
632                 public void DoCount ()
633                 {
634                         while (true) {
635                                 counter++;
636                                 Thread.Sleep (1);
637                         }
638                 }
639         }
640         
641         public class TestUtil
642         {
643                 public static void WaitForNotAlive (Thread t, string s)
644                 {
645                         WhileAlive (t, true, s);
646                 }
647                 
648                 public static void WaitForAlive (Thread t, string s)
649                 {
650                         WhileAlive (t, false, s);
651                 }
652                 
653                 public static bool WaitForAliveOrStop (Thread t, string s)
654                 {
655                         return WhileAliveOrStop (t, false, s);
656                 }
657                 
658                 public static void WhileAlive (Thread t, bool alive, string s)
659                 {
660                         DateTime ti = DateTime.Now;
661                         while (t.IsAlive == alive) {
662                                 if ((DateTime.Now - ti).TotalSeconds > 10) {
663                                         if (alive) Assertion.Fail ("Timeout while waiting for not alive state. " + s);
664                                         else Assertion.Fail ("Timeout while waiting for alive state. " + s);
665                                 }
666                         }
667                 }
668
669                 public static bool WhileAliveOrStop (Thread t, bool alive, string s)
670                 {
671                         DateTime ti = DateTime.Now;
672                         while (t.IsAlive == alive) {
673                                 if (t.ThreadState == ThreadState.Stopped)
674                                         return false;
675
676                                 if ((DateTime.Now - ti).TotalSeconds > 10) {
677                                         if (alive) Assertion.Fail ("Timeout while waiting for not alive state. " + s);
678                                         else Assertion.Fail ("Timeout while waiting for alive state. " + s);
679                                 }
680                         }
681
682                         return true;
683                 }
684         }
685 }