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