[corlib] Remove multiple appdomain support (AppDomain.CreateDomain, etc) from tvOS...
[mono.git] / mcs / class / corlib / Test / System.Threading / ThreadTest.cs
index 8c82931acc57fba450bead9ffc2953adab6b20b6..5773a1003f63821a3440ca8289347d5b6d6346c5 100644 (file)
@@ -13,6 +13,9 @@ using System;
 using System.Globalization;
 using System.Security.Principal;
 using System.Threading;
+using System.Reflection;
+using System.Collections.Generic;
+using SD = System.Diagnostics;
 
 using NUnit.Framework;
 
@@ -85,10 +88,10 @@ namespace MonoTests.System.Threading
        [Category("MobileNotWorking")] // Abort #10240
        public class ThreadTest
        {
-               TimeSpan Infinite = new TimeSpan (-10000);      // -10000 ticks == -1 ms
+               //TimeSpan Infinite = new TimeSpan (-10000);    // -10000 ticks == -1 ms
                TimeSpan SmallNegative = new TimeSpan (-2);     // between 0 and -1.0 (infinite) ms
                TimeSpan Negative = new TimeSpan (-20000);      // really negative
-               TimeSpan MaxValue = TimeSpan.FromMilliseconds ((long) Int32.MaxValue);
+               //TimeSpan MaxValue = TimeSpan.FromMilliseconds ((long) Int32.MaxValue);
                TimeSpan TooLarge = TimeSpan.FromMilliseconds ((long) Int32.MaxValue + 1);
 
                static bool is_win32;
@@ -181,7 +184,11 @@ namespace MonoTests.System.Threading
                        {
                                sub_thread.Start();
                                Thread.Sleep (100);
+#if MONO_FEATURE_THREAD_ABORT
                                sub_thread.Abort();
+#else
+                               sub_thread.Interrupt ();
+#endif
                        }
                }
                
@@ -212,10 +219,18 @@ namespace MonoTests.System.Threading
                                thread2.Start();
                                TestUtil.WaitForAlive (thread2, "wait2");
                                T2ON = true;
+#if MONO_FEATURE_THREAD_ABORT
                                thread1.Abort();
+#else
+                               thread1.Interrupt ();
+#endif
                                TestUtil.WaitForNotAlive (thread1, "wait3");
                                T1ON = false;
+#if MONO_FEATURE_THREAD_ABORT
                                thread2.Abort();
+#else
+                               thread2.Interrupt ();
+#endif
                                TestUtil.WaitForNotAlive (thread2, "wait4");
                                T2ON = false;
                        }
@@ -260,38 +275,29 @@ namespace MonoTests.System.Threading
                        C1Test test1 = new C1Test ();
                        Thread tA = new Thread (new ThreadStart (test1.TestMethod));
                        int hA1 = tA.GetHashCode ();
-#if NET_2_0
                        Assert.IsTrue (hA1 > 0, "#A1");
-#endif
                        tA.Start ();
                        int hA2 = tA.GetHashCode ();
                        Assert.AreEqual (hA1, hA2, "#A2");
                        tA.Join ();
                        int hA3 = tA.GetHashCode ();
                        Assert.AreEqual (hA1, hA3, "#A3");
-#if NET_2_0
                        Assert.AreEqual (hA1, tA.ManagedThreadId, "#A4");
-#endif
 
                        test1 = new C1Test ();
                        Thread tB = new Thread (new ThreadStart (test1.TestMethod));
                        int hB1 = tB.GetHashCode ();
-#if NET_2_0
                        Assert.IsTrue (hB1 > 0, "#B1");
-#endif
                        tB.Start ();
                        int hB2 = tB.GetHashCode ();
                        Assert.AreEqual (hB1, hB2, "#B2");
                        tB.Join ();
                        int hB3 = tB.GetHashCode ();
                        Assert.AreEqual (hB1, hB3, "#B3");
-#if NET_2_0
                        Assert.AreEqual (hB1, tB.ManagedThreadId, "#B4");
-#endif
                        Assert.IsFalse (hA2 == hB2, "#B5");
                }
 
-#if NET_2_0
                [Test] // bug #82700
                public void ManagedThreadId ()
                {
@@ -316,7 +322,6 @@ namespace MonoTests.System.Threading
                        Assert.AreEqual (mtB2, mtB3, "#B2");
                        Assert.IsFalse (mtB1 == mtA1, "#B3");
                }
-#endif
 
                [Test]
                [Category ("NotDotNet")] // it hangs.
@@ -335,7 +340,11 @@ namespace MonoTests.System.Threading
                        C2Test test1 = new C2Test();
                        Thread TestThread = new Thread(new ThreadStart(test1.TestMethod));
                        TestThread.Start();
+#if MONO_FEATURE_THREAD_ABORT
                        TestThread.Abort();
+#else
+                       TestThread.Interrupt ();
+#endif
                        try {
                                TestThread.Start();
                                Assert.Fail ("#2");
@@ -350,7 +359,11 @@ namespace MonoTests.System.Threading
                        }
                        bool started = (TestThread.ThreadState == ThreadState.Running);
                        Assert.AreEqual (started, test1.run, "#15 Thread Is not in the correct state: ");
+#if MONO_FEATURE_THREAD_ABORT
                        TestThread.Abort();
+#else
+                       TestThread.Interrupt ();
+#endif
                }
                }
 
@@ -365,12 +378,12 @@ namespace MonoTests.System.Threading
                        Assert.AreEqual (ApartmentState.Unknown, TestThread.ApartmentState, "#1");
                        TestThread.Start();
                        TestUtil.WaitForAlive (TestThread, "wait5");
-#if NET_2_0
                        Assert.AreEqual (ApartmentState.MTA, TestThread.ApartmentState, "#2");
+#if MONO_FEATURE_THREAD_ABORT
+                       TestThread.Abort();
 #else
-                       Assert.AreEqual (ApartmentState.Unknown, TestThread.ApartmentState, "#3");
+                       TestThread.Interrupt ();
 #endif
-                       TestThread.Abort();
                }
 
                [Test]
@@ -389,10 +402,15 @@ namespace MonoTests.System.Threading
                                ThreadPriority before = TestThread.Priority;
                                Assert.AreEqual (before, after, "#41 Unexpected Priority Change: ");
                        } finally {
+#if MONO_FEATURE_THREAD_ABORT
                                TestThread.Abort();
+#else
+                               TestThread.Interrupt ();
+#endif
                        }
                }
 
+#if MONO_FEATURE_THREAD_ABORT
                [Test]
                [Category ("NotDotNet")] // on MS, Thread is still in AbortRequested state when Start is invoked
                public void AbortUnstarted ()
@@ -402,6 +420,7 @@ namespace MonoTests.System.Threading
                        th.Abort ();
                        th.Start ();
                }
+#endif
 
                [Test]
                [Category ("NotDotNet")] // on MS, ThreadState is immediately Stopped after Abort
@@ -416,7 +435,11 @@ namespace MonoTests.System.Threading
                                TestUtil.WaitForAliveOrStop (TestThread, "wait8");
                                Assert.AreEqual (ThreadPriority.Normal, TestThread.Priority, "#43 Incorrect Priority in Started thread: ");
                        } finally {
+#if MONO_FEATURE_THREAD_ABORT
                                TestThread.Abort();
+#else
+                               TestThread.Interrupt ();
+#endif
                        }
                        Assert.AreEqual (ThreadPriority.Normal, TestThread.Priority, "#44 Incorrect Priority in Aborted thread: ");
                }
@@ -441,7 +464,11 @@ namespace MonoTests.System.Threading
                                Assert.AreEqual (ThreadPriority.Highest, TestThread.Priority, "#45E Incorrect Priority:");
                        }
                        finally {
+#if MONO_FEATURE_THREAD_ABORT
                                TestThread.Abort();
+#else
+                               TestThread.Interrupt ();
+#endif
                        }
                }
 
@@ -469,7 +496,11 @@ namespace MonoTests.System.Threading
                                bool state = TestThread.IsBackground;
                                Assert.IsFalse (state, "#51 IsBackground not set at the default state: ");
                        } finally {
+#if MONO_FEATURE_THREAD_ABORT
                                TestThread.Abort();
+#else
+                               TestThread.Interrupt ();
+#endif
                        }
                }
 
@@ -482,7 +513,11 @@ namespace MonoTests.System.Threading
                        try {
                                TestThread.Start();
                        } finally {
+#if MONO_FEATURE_THREAD_ABORT
                                TestThread.Abort();
+#else
+                               TestThread.Interrupt ();
+#endif
                        }
                        
                        if (TestThread.IsAlive) {
@@ -511,7 +546,11 @@ namespace MonoTests.System.Threading
                                TestThread.Name = newname;
                                Assert.AreEqual (newname, TestThread.Name, "#62 Name not set when must be set: ");
                        } finally {
+#if MONO_FEATURE_THREAD_ABORT
                                TestThread.Abort();
+#else
+                               TestThread.Interrupt ();
+#endif
                        }
                }
 
@@ -526,13 +565,44 @@ namespace MonoTests.System.Threading
 
                [Test]
                [ExpectedException (typeof (InvalidOperationException))]
-               public void ReName ()
+               public void Rename ()
                {
-                       Thread t = new Thread (new ThreadStart (ReName));
+                       Thread t = new Thread (new ThreadStart (Rename));
                        t.Name = "a";
                        t.Name = "b";
                }
 
+               bool rename_finished;
+               bool rename_failed;
+
+               [Test]
+               public void RenameTpThread ()
+               {
+                       object monitor = new object ();
+                       ThreadPool.QueueUserWorkItem (new WaitCallback (Rename_callback), monitor);
+                       lock (monitor) {
+                               if (!rename_finished)
+                                       Monitor.Wait (monitor);
+                       }
+                       Assert.IsTrue (!rename_failed);
+               }
+
+               void Rename_callback (object o) {
+                       Thread.CurrentThread.Name = "a";
+                       try {
+                               Thread.CurrentThread.Name = "b";
+                               //Console.WriteLine ("Thread name is: {0}", Thread.CurrentThread.Name);
+                       } catch (Exception e) {
+                               //Console.Error.WriteLine (e);
+                               rename_failed = true;
+                       }
+                       object monitor = o;
+                       lock (monitor) {
+                               rename_finished = true;
+                               Monitor.Pulse (monitor);
+                       }
+               }
+
                [Test]
                public void TestNestedThreads1()
                {
@@ -542,7 +612,11 @@ namespace MonoTests.System.Threading
                                TestThread.Start();
                                TestUtil.WaitForAlive (TestThread, "wait11");
                        } finally {
+#if MONO_FEATURE_THREAD_ABORT
                                TestThread.Abort();
+#else
+                               TestThread.Interrupt ();
+#endif
                        }
                }
 
@@ -554,7 +628,11 @@ namespace MonoTests.System.Threading
                        try {
                                TestThread.Start();
                        } finally {
+#if MONO_FEATURE_THREAD_ABORT
                                TestThread.Abort();
+#else
+                               TestThread.Interrupt ();
+#endif
                        }
                }
 
@@ -570,8 +648,13 @@ namespace MonoTests.System.Threading
                                thread2.Start();
                                thread2.Join();
                        } finally {
+#if MONO_FEATURE_THREAD_ABORT
                                thread1.Abort();
                                thread2.Abort();
+#else
+                               thread1.Interrupt ();
+                               thread2.Interrupt ();
+#endif
                        }
                }
 
@@ -656,7 +739,11 @@ namespace MonoTests.System.Threading
                                Assert.IsTrue (TestThread.ThreadState == ThreadState.Running || (TestThread.ThreadState & ThreadState.Unstarted) != 0,
                                        "#102 Wrong Thread State: " + TestThread.ThreadState.ToString ());
                        } finally {
+#if MONO_FEATURE_THREAD_ABORT
                                TestThread.Abort();
+#else
+                               TestThread.Interrupt ();
+#endif
                        }
                        
                        TestUtil.WaitForNotAlive (TestThread, "wait12");
@@ -676,7 +763,11 @@ namespace MonoTests.System.Threading
                                t.Start ();
                                t.Join ();
                        } catch {
+#if MONO_FEATURE_THREAD_ABORT
                                t.Abort ();
+#else
+                               t.Interrupt ();
+#endif
                        }
                }
 
@@ -691,7 +782,11 @@ namespace MonoTests.System.Threading
                                t.Start ();
                                t.Join ();
                        } catch {
+#if MONO_FEATURE_THREAD_ABORT
                                t.Abort ();
+#else
+                               t.Interrupt ();
+#endif
                        }
                }
 
@@ -705,7 +800,11 @@ namespace MonoTests.System.Threading
                                t.Start ();
                                t.Join ();
                        } catch {
+#if MONO_FEATURE_THREAD_ABORT
                                t.Abort ();
+#else
+                               t.Interrupt ();
+#endif
                        }
                }
                
@@ -719,12 +818,17 @@ namespace MonoTests.System.Threading
                                t.Start ();
                                t.Join ();
                        } catch {
+#if MONO_FEATURE_THREAD_ABORT
                                t.Abort ();
+#else
+                               t.Interrupt ();
+#endif
                        }
                }
 
                int counter = 0;
 
+#if MONO_FEATURE_THREAD_SUSPEND_RESUME
                [Test]
                public void TestSuspend ()
                {
@@ -748,7 +852,9 @@ namespace MonoTests.System.Threading
                        TestUtil.WaitForNotAlive (t, "wait13");
                        CheckIsNotRunning ("t6", t);
                }
-
+#endif
+               
+#if MONO_FEATURE_THREAD_SUSPEND_RESUME && MONO_FEATURE_THREAD_ABORT
                [Test]
                [Category("NotDotNet")] // On MS, ThreadStateException is thrown on Abort: "Thread is suspended; attempting to abort"
                public void TestSuspendAbort ()
@@ -779,19 +885,22 @@ namespace MonoTests.System.Threading
                        
                        CheckIsNotRunning ("t6", t);
                }
+#endif
 
                [Test]
                public void Test_Interrupt ()
                {
+                       ManualResetEvent mre = new ManualResetEvent (false);
                        bool interruptedExceptionThrown = false;
+
                        ThreadPool.QueueUserWorkItem (Test_Interrupt_Worker, Thread.CurrentThread);
 
                        try {
                                try {
-                                       Thread.Sleep (3000);
+                                       mre.WaitOne (3000);
                                } finally {
                                        try {
-                                               Thread.Sleep (0);
+                                               mre.WaitOne (0);
                                        } catch (ThreadInterruptedException) {
                                                Assert.Fail ("ThreadInterruptedException thrown twice");
                                        }
@@ -821,11 +930,12 @@ namespace MonoTests.System.Threading
                [Category ("NotDotNet")] // it crashes nunit.
                public void Test_InterruptCurrentThread ()
                {
+                       ManualResetEvent mre = new ManualResetEvent (false);
                        bool interruptedExceptionThrown = false;
 
                        Thread.CurrentThread.Interrupt ();
                        try {
-                               Thread.Sleep (0);
+                               mre.WaitOne (0);
                                Assert.Fail ();
                        } catch (ThreadInterruptedException) {
                        }
@@ -838,6 +948,34 @@ namespace MonoTests.System.Threading
                        Assert.AreSame (Thread.GetNamedDataSlot ("te#st"), Thread.GetNamedDataSlot ("te#st"), "#2");
                }
 
+               class DomainClass : MarshalByRefObject {
+                       Thread m_thread;
+                       bool success;
+
+                       public bool Run () {
+                               m_thread = new Thread(ThreadProc);
+                               m_thread.Start(Thread.CurrentThread);
+                               m_thread.Join();
+                               return success;
+                       }
+
+                       public void ThreadProc (object arg) {
+                               success = m_thread == Thread.CurrentThread;
+                       }
+               }
+
+#if MONO_FEATURE_MULTIPLE_APPDOMAINS
+               [Test]
+               public void CurrentThread_Domains ()
+               {
+                       AppDomain ad = AppDomain.CreateDomain ("foo");
+                       ad.Load (typeof (DomainClass).Assembly.GetName ());
+                       var o = (DomainClass)ad.CreateInstanceAndUnwrap (typeof (DomainClass).Assembly.FullName, typeof (DomainClass).FullName);
+                       Assert.IsTrue (o.Run ());
+                       AppDomain.Unload (ad);
+               }
+#endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
+
                void CheckIsRunning (string s, Thread t)
                {
                        int c = counter;
@@ -1106,11 +1244,7 @@ namespace MonoTests.System.Threading
                                exception_occured = true;
                        }
                        Assert.AreEqual (ApartmentState.Unknown, t3.ApartmentState, "Thread3 Set Invalid");
-#if NET_2_0
                        Assert.IsFalse (exception_occured, "Thread3 Set Invalid Exception Occured");
-#else
-                       Assert.IsTrue (exception_occured, "Thread3 Set Invalid Exception Occured");
-#endif
 
                        t1.Start ();
                        exception_occured = false;
@@ -1233,6 +1367,17 @@ namespace MonoTests.System.Threading
                static void ThreadProc(Object stateInfo) {
                        Thread.CurrentThread.Name = "My Worker";
                }
+
+               [Test]
+               public void GetStackTraces () {
+                       var m = typeof (Thread).GetMethod ("Mono_GetStackTraces", BindingFlags.NonPublic|BindingFlags.Static);
+                       if (m != null) {
+                               var res = (Dictionary<Thread,SD.StackTrace>)typeof (Thread).GetMethod ("Mono_GetStackTraces", BindingFlags.NonPublic|BindingFlags.Static).Invoke (null, null);
+                               foreach (var t in res.Keys) {
+                                       var st = res [t].ToString ();
+                               }
+                       }
+               }
        }
 
        public class TestUtil