Jelajahi Sumber

Fix xamarin-android issue 1130 and add test (#6326)

Katelyn Gadd 7 tahun lalu
induk
melakukan
d45fb4e882

+ 6 - 0
mcs/class/corlib/System.Threading/Thread.cs

@@ -245,6 +245,10 @@ namespace System.Threading {
 			get {
 				Thread th = CurrentThread;
 
+				var logicalPrincipal = th.GetExecutionContextReader().LogicalCallContext.Principal;
+				if (logicalPrincipal != null)
+					return logicalPrincipal;
+
 				if (th.principal_version != th.Internal._serialized_principal_version)
 					th.principal = null;
 
@@ -266,6 +270,8 @@ namespace System.Threading {
 			set {
 				Thread th = CurrentThread;
 
+				th.GetMutableExecutionContext().LogicalCallContext.Principal = value;
+
 				if (value != GetDomain ().DefaultPrincipal) {
 					++th.Internal._serialized_principal_version;
 					try {

+ 76 - 0
mcs/class/corlib/Test/System.Threading/ThreadPrincipalTests.cs

@@ -0,0 +1,76 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using NUnit.Framework;
+using System.Security;
+using System.Security.Permissions;
+using System.Security.Principal;
+
+namespace MonoTests.System.Threading.Tasks
+{
+    [TestFixture]
+    public class ThreadPrincipalTests
+    {   
+        [Test]
+        public void PrincipalFlowsToAsyncTask ()
+        {
+            var t = _PrincipalFlowsToAsyncTask();
+            t.GetAwaiter().GetResult();
+        }
+
+        public async Task _PrincipalFlowsToAsyncTask ()
+        {    
+            var mockIdentity = new MockIdentity {
+                AuthenticationType = "authtype",
+                IsAuthenticated = true,
+                Name = "name"
+            };
+            var mockPrincipal = new MockPrincipal {
+                Identity = mockIdentity
+            };          
+            var oldPrincipal = Thread.CurrentPrincipal;
+            Thread.CurrentPrincipal = mockPrincipal;          
+
+            try {
+                await Task.Factory.StartNew(async () =>
+                {
+                    var newThreadId = Thread.CurrentThread.ManagedThreadId; // on different thread.
+                    Assert.IsTrue(Thread.CurrentPrincipal.Identity.IsAuthenticated);
+                    Assert.AreEqual(mockPrincipal, Thread.CurrentPrincipal);
+                   
+                    await Task.Factory.StartNew(() =>
+                    {
+                        // still works even when nesting..
+                        newThreadId = Thread.CurrentThread.ManagedThreadId;
+                        Assert.IsTrue(Thread.CurrentPrincipal.Identity.IsAuthenticated);
+                        Assert.AreEqual(mockPrincipal, Thread.CurrentPrincipal);
+
+                    }, TaskCreationOptions.LongRunning);
+                }, TaskCreationOptions.LongRunning);
+
+                await Task.Run(() =>
+                {
+                    // Following works on NET4.7 and fails under Xamarin.Android.
+                    var newThreadId = Thread.CurrentThread.ManagedThreadId;
+                    Assert.IsTrue(Thread.CurrentPrincipal.Identity.IsAuthenticated);
+                    Assert.AreEqual(mockPrincipal, Thread.CurrentPrincipal);
+                });
+            } finally {
+                Thread.CurrentPrincipal = oldPrincipal;
+            }
+        }
+    }
+
+    public class MockPrincipal : IPrincipal {
+        public IIdentity Identity { get; set; }
+        public bool IsInRole (string role) {
+            return true;
+        }
+    }
+
+    public class MockIdentity : IIdentity {
+        public string AuthenticationType { get; set; }
+        public bool IsAuthenticated { get; set; }
+        public string Name { get; set; }
+    }
+}

+ 1 - 0
mcs/class/corlib/corlib_test.dll.sources

@@ -545,3 +545,4 @@ System.Threading/ThreadLocalTests.cs
 System.Threading/SpinLockTests.cs
 ../../../../mono/mini/TestHelpers.cs
 ../../test-helpers/NunitHelpers.cs
+System.Threading/ThreadPrincipalTests.cs