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