RunTestInBackgroundThread() public static method

public static RunTestInBackgroundThread ( Action test ) : void
test Action
return void
Example #1
0
        public void CrossProcess_NamedMutex_ProtectedFileAccessAtomic(string prefix)
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                string mutexName = prefix + Guid.NewGuid().ToString("N");
                string fileName  = GetTestFilePath();

                Action <string, string> otherProcess = (m, f) =>
                {
                    using (var mutex = Mutex.OpenExisting(m))
                    {
                        mutex.CheckedWait();
                        try
                        { File.WriteAllText(f, "0"); }
                        finally { mutex.ReleaseMutex(); }

                        IncrementValueInFileNTimes(mutex, f, 10);
                    }
                };

                using (var mutex = new Mutex(false, mutexName))
                    using (var remote = RemoteExecutor.Invoke(otherProcess, mutexName, fileName))
                    {
                        SpinWait.SpinUntil(() => File.Exists(fileName), ThreadTestHelpers.UnexpectedTimeoutMilliseconds);

                        IncrementValueInFileNTimes(mutex, fileName, 10);
                    }

                Assert.Equal(20, int.Parse(File.ReadAllText(fileName)));
            });
        }
Example #2
0
        public void AbandonExisting(string name, int waitType)
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                using (var m = new Mutex(false, name))
                {
                    Task t = Task.Factory.StartNew(() =>
                    {
                        Assert.True(m.WaitOne(FailedWaitTimeout));
                        // don't release the mutex; abandon it on this thread
                    }, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default);
                    Assert.True(t.Wait(FailedWaitTimeout));

                    switch (waitType)
                    {
                    case 0:     // WaitOne
                        Assert.Throws <AbandonedMutexException>(() => m.WaitOne(FailedWaitTimeout));
                        break;

                    case 1:     // WaitAny
                        AbandonedMutexException ame = Assert.Throws <AbandonedMutexException>(() => WaitHandle.WaitAny(new[] { m }, FailedWaitTimeout));
                        Assert.Equal(0, ame.MutexIndex);
                        Assert.Equal(m, ame.Mutex);
                        break;
                    }
                }
            });
        }
Example #3
0
        public void CrossProcess_NamedMutex_ProtectedFileAccessAtomic(string prefix)
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                string mutexName = prefix + Guid.NewGuid().ToString("N");
                string fileName  = GetTestFilePath();

                Func <string, string, int> otherProcess = (m, f) =>
                {
                    using (var mutex = Mutex.OpenExisting(m))
                    {
                        mutex.WaitOne();
                        try
                        { File.WriteAllText(f, "0"); }
                        finally { mutex.ReleaseMutex(); }

                        IncrementValueInFileNTimes(mutex, f, 10);
                    }
                    return(SuccessExitCode);
                };

                using (var mutex = new Mutex(false, mutexName))
                    using (var remote = RemoteInvoke(otherProcess, mutexName, $"\"{fileName}\""))
                    {
                        SpinWait.SpinUntil(() => File.Exists(fileName));

                        IncrementValueInFileNTimes(mutex, fileName, 10);
                    }

                Assert.Equal(20, int.Parse(File.ReadAllText(fileName)));
            });
        }
Example #4
0
        private static void VerifyExecutionContextFlow(AsyncLocal <int> asyncLocal, int expectedValue)
        {
            Assert.Equal(expectedValue == 0, ExecutionContext.IsFlowSuppressed());
            if (ExecutionContext.IsFlowSuppressed())
            {
                Assert.Null(ExecutionContext.Capture());
            }
            VerifyExecutionContext(ExecutionContext.Capture(), asyncLocal, expectedValue);

            // Creating a thread flows context if and only if flow is not suppressed
            int asyncLocalValue = -1;

            ThreadTestHelpers.RunTestInBackgroundThread(() => asyncLocalValue = asyncLocal.Value);
            Assert.Equal(expectedValue, asyncLocalValue);

            // Queueing a thread pool work item flows context if and only if flow is not suppressed
            asyncLocalValue = -1;
            var done = new AutoResetEvent(false);

            ThreadPool.QueueUserWorkItem(state =>
            {
                asyncLocalValue = asyncLocal.Value;
                done.Set();
            });
            done.CheckedWait();
            Assert.Equal(expectedValue, asyncLocalValue);
        }
        public static void InvalidLockCookieTest()
        {
            // Invalid lock cookie created by using one up with Upgrade/Downgrade
            var            trwl = new TestReaderWriterLock();
            TestLockCookie tlc  = trwl.UpgradeToWriterLock();

            trwl.DowngradeFromWriterLock(tlc);
            trwl.AcquireWriterLock();
            trwl.DowngradeFromWriterLock(tlc, InvalidLockCookieExceptionHResult);
            trwl.ReleaseWriterLock();
            trwl.RestoreLock(tlc, InvalidLockCookieExceptionHResult);

            // Invalid lock cookie created by using one up with Release/Restore
            tlc = trwl.ReleaseLock();
            trwl.RestoreLock(tlc);
            trwl.AcquireWriterLock();
            trwl.DowngradeFromWriterLock(tlc, InvalidLockCookieExceptionHResult);
            trwl.ReleaseWriterLock();
            trwl.RestoreLock(tlc, InvalidLockCookieExceptionHResult);

            // Lock cookie owned by another thread
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                TestLockCookie tlc2 = trwl.UpgradeToWriterLock();
                tlc = tlc2.Clone();
                trwl.DowngradeFromWriterLock(tlc2);
            });
            trwl.AcquireWriterLock();
            trwl.DowngradeFromWriterLock(tlc, InvalidLockCookieExceptionHResult);
            trwl.ReleaseWriterLock();
            trwl.RestoreLock(tlc, InvalidLockCookieExceptionHResult);

            trwl.Dispose();
        }
Example #6
0
        public static void BasicTest()
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                var hecm = new HostExecutionContextManager();
                Assert.Null(hecm.Capture());
                Assert.Throws <InvalidOperationException>(() => hecm.SetHostExecutionContext(null));

                var hec0 = new HostExecutionContext();
                var hec1 = new HostExecutionContext();
                object previousState0 = hecm.SetHostExecutionContext(hec0);
                ExecutionContext ec   = ExecutionContext.Capture();
                object previousState1 = hecm.SetHostExecutionContext(hec1);

                Assert.Throws <InvalidOperationException>(() => hecm.Revert(null));
                Assert.Throws <InvalidOperationException>(() => hecm.Revert(new object()));
                Assert.Throws <InvalidOperationException>(() => hecm.Revert(previousState0));

                object otherThreadState = null;
                ThreadTestHelpers.RunTestInBackgroundThread(
                    () => otherThreadState = hecm.SetHostExecutionContext(new HostExecutionContext()));
                Assert.Throws <InvalidOperationException>(() => hecm.Revert(otherThreadState));

                ExecutionContext.Run(
                    ec,
                    state => Assert.Throws <InvalidOperationException>(() => hecm.Revert(previousState1)),
                    null);

                hecm.Revert(previousState1);
                Assert.Throws <InvalidOperationException>(() => hecm.Revert(previousState1));

                // Revert always reverts to a null host execution context when it's not hosted
                Assert.Throws <InvalidOperationException>(() => hecm.Revert(previousState0));
            });
        }
Example #7
0
        [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotInAppContainer))] // Can't create global objects in appcontainer
        public void Ctor_ImpersonateAnonymousAndTryCreateGlobalMutexTest()
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                if (!ImpersonateAnonymousToken(GetCurrentThread()))
                {
                    // Impersonation is not allowed in the current context, this test is inappropriate in such a case
                    return;
                }

                Assert.Throws <UnauthorizedAccessException>(() => new Mutex(false, "Global\\" + Guid.NewGuid().ToString("N")));
                Assert.True(RevertToSelf());
            });
        }
Example #8
0
 public static void CreateCopyTest()
 {
     ThreadTestHelpers.RunTestInBackgroundThread(() =>
     {
         var asyncLocal = new AsyncLocal <int>();
         ExecutionContext executionContext = ExecutionContext.Capture();
         VerifyExecutionContext(executionContext, asyncLocal, 0);
         executionContext = ExecutionContext.Capture();
         ExecutionContext executionContextCopy0 = executionContext.CreateCopy();
         asyncLocal.Value = 1;
         executionContext = ExecutionContext.Capture();
         VerifyExecutionContext(executionContext, asyncLocal, 1);
         VerifyExecutionContext(executionContextCopy0, asyncLocal, 0);
         executionContext = ExecutionContext.Capture();
         ExecutionContext executionContextCopy1 = executionContext.CreateCopy();
         VerifyExecutionContext(executionContextCopy1, asyncLocal, 1);
     });
 }
Example #9
0
        public static void CaptureThenSuppressThenRunFlowTest()
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                var asyncLocal   = new AsyncLocal <int>();
                asyncLocal.Value = 1;

                ExecutionContext executionContext = ExecutionContext.Capture();
                ExecutionContext.SuppressFlow();
                ExecutionContext.Run(
                    executionContext,
                    state =>
                {
                    Assert.Equal(1, asyncLocal.Value);
                    VerifyExecutionContextFlow(asyncLocal, 1);
                },
                    null);
                Assert.Equal(1, asyncLocal.Value);
                VerifyExecutionContextFlow(asyncLocal, 0);
                ExecutionContext.RestoreFlow();
                VerifyExecutionContextFlow(asyncLocal, 1);

                executionContext = ExecutionContext.Capture();
                asyncLocal.Value = 2;
                ExecutionContext.SuppressFlow();
                Assert.True(ExecutionContext.IsFlowSuppressed());
                ExecutionContext.Run(
                    executionContext,
                    state =>
                {
                    Assert.Equal(1, asyncLocal.Value);
                    VerifyExecutionContextFlow(asyncLocal, 1);
                },
                    null);
                Assert.Equal(2, asyncLocal.Value);
                VerifyExecutionContextFlow(asyncLocal, 0);
                ExecutionContext.RestoreFlow();
                VerifyExecutionContextFlow(asyncLocal, 2);
            });
        }
        public static void SerializationTest()
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                var asyncLocal   = new AsyncLocal <int>();
                asyncLocal.Value = 1;
                ExecutionContext executionContext = ExecutionContext.Capture();
                VerifyExecutionContext(executionContext, asyncLocal, 1);

                Assert.Throws <ArgumentNullException>(() => executionContext.GetObjectData(null, new StreamingContext()));

                var binaryFormatter = new BinaryFormatter();
                var memoryStream    = new MemoryStream();
                binaryFormatter.Serialize(memoryStream, executionContext);
                memoryStream.Close();
                byte[] binaryData = memoryStream.ToArray();

                memoryStream     = new MemoryStream(binaryData);
                executionContext = (ExecutionContext)binaryFormatter.Deserialize(memoryStream);
                memoryStream.Close();
            });
        }
Example #11
0
        public static void AsyncFlowControlTest()
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                Action <AsyncFlowControl, AsyncFlowControl, bool> verifyEquality =
                    (afc0, afc1, areExpectedToBeEqual) =>
                {
                    Assert.Equal(areExpectedToBeEqual, afc0.Equals(afc1));
                    Assert.Equal(areExpectedToBeEqual, afc0.Equals((object)afc1));
                    Assert.Equal(areExpectedToBeEqual, afc0 == afc1);
                    Assert.NotEqual(areExpectedToBeEqual, afc0 != afc1);
                };

                AsyncFlowControl asyncFlowControl0 = ExecutionContext.SuppressFlow();
                ExecutionContext.RestoreFlow();
                AsyncFlowControl asyncFlowControl1 = ExecutionContext.SuppressFlow();
                ExecutionContext.RestoreFlow();
                verifyEquality(asyncFlowControl0, asyncFlowControl1, true);
                verifyEquality(asyncFlowControl1, asyncFlowControl0, true);

                var asyncLocal    = new AsyncLocal <int>();
                asyncLocal.Value  = 1;
                asyncFlowControl1 = ExecutionContext.SuppressFlow();
                ExecutionContext.RestoreFlow();
                verifyEquality(asyncFlowControl0, asyncFlowControl1, true);
                verifyEquality(asyncFlowControl1, asyncFlowControl0, true);

                asyncFlowControl1 = new AsyncFlowControl();
                verifyEquality(asyncFlowControl0, asyncFlowControl1, false);
                verifyEquality(asyncFlowControl1, asyncFlowControl0, false);

                ThreadTestHelpers.RunTestInBackgroundThread(() => asyncFlowControl1 = ExecutionContext.SuppressFlow());
                verifyEquality(asyncFlowControl0, asyncFlowControl1, false);
                verifyEquality(asyncFlowControl1, asyncFlowControl0, false);
            });
        }
Example #12
0
 public void Ctor_TryCreateGlobalMutexTest_Uwp()
 {
     ThreadTestHelpers.RunTestInBackgroundThread(() =>
                                                 Assert.Throws <UnauthorizedAccessException>(() => new Mutex(false, "Global\\" + Guid.NewGuid().ToString("N"))));
 }
        public static void WaitNotificationTest()
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                var tsc = new TestSynchronizationContext();
                SynchronizationContext.SetSynchronizationContext(tsc);
                Assert.Same(tsc, SynchronizationContext.Current);

                var e          = new ManualResetEvent(false);
                tsc.WaitAction = () => e.Set();
                Assert.False(tsc.IsWaitNotificationRequired());
                Assert.False(e.WaitOne(0));
                tsc.SetWaitNotificationRequired();
                Assert.True(tsc.IsWaitNotificationRequired());
                Assert.True(e.WaitOne(0));

                var mres       = new ManualResetEventSlim();
                tsc.WaitAction = () => mres.Set();
                mres.Reset();
                mres.CheckedWait();

                e.Reset();
                tsc.WaitAction = () => e.Set();
                SynchronizationContext.SetSynchronizationContext(new TestSynchronizationContext());
                Assert.False(e.WaitOne(0));
                SynchronizationContext.SetSynchronizationContext(tsc);
                Assert.True(e.WaitOne(0));
                e.Reset();
                e.CheckedWait();

                e.Reset();
                var lockObj = new object();
                var lockAcquiredFromBackground = new AutoResetEvent(false);
                Action waitForThread;
                Thread t =
                    ThreadTestHelpers.CreateGuardedThread(out waitForThread, () =>
                {
                    lock (lockObj)
                    {
                        lockAcquiredFromBackground.Set();
                        e.CheckedWait();
                    }
                });
                t.IsBackground = true;
                t.Start();
                lockAcquiredFromBackground.CheckedWait();
                Assert.True(Monitor.TryEnter(lockObj, ThreadTestHelpers.UnexpectedTimeoutMilliseconds));
                Monitor.Exit(lockObj);
                waitForThread();

                e.Reset();
                var m = new Mutex();
                t     = ThreadTestHelpers.CreateGuardedThread(out waitForThread, () =>
                {
                    m.CheckedWait();
                    try
                    {
                        lockAcquiredFromBackground.Set();
                        e.CheckedWait();
                    }
                    finally
                    {
                        m.ReleaseMutex();
                    }
                });
                t.IsBackground = true;
                t.Start();
                lockAcquiredFromBackground.CheckedWait();
                m.CheckedWait();
                m.ReleaseMutex();
                waitForThread();
            });
        }
Example #14
0
        public static void FlowTest()
        {
            ThreadTestHelpers.RunTestInBackgroundThread(() =>
            {
                var asyncLocal   = new AsyncLocal <int>();
                asyncLocal.Value = 1;

                var asyncFlowControl = default(AsyncFlowControl);
                Action <Action, Action> verifySuppressRestore =
                    (suppressFlow, restoreFlow) =>
                {
                    VerifyExecutionContextFlow(asyncLocal, 1);
                    ExecutionContext executionContext2 = ExecutionContext.Capture();

                    suppressFlow();
                    VerifyExecutionContextFlow(asyncLocal, 0);
                    VerifyExecutionContext(executionContext2, asyncLocal, 1);
                    executionContext2 = ExecutionContext.Capture();

                    restoreFlow();
                    VerifyExecutionContextFlow(asyncLocal, 1);
                    VerifyExecutionContext(executionContext2, asyncLocal, 0);
                };

                verifySuppressRestore(
                    () => asyncFlowControl = ExecutionContext.SuppressFlow(),
                    () => asyncFlowControl.Undo());
                verifySuppressRestore(
                    () => asyncFlowControl = ExecutionContext.SuppressFlow(),
                    () => asyncFlowControl.Dispose());
                verifySuppressRestore(
                    () => ExecutionContext.SuppressFlow(),
                    () => ExecutionContext.RestoreFlow());

                Assert.Throws <InvalidOperationException>(() => ExecutionContext.RestoreFlow());
                asyncFlowControl = ExecutionContext.SuppressFlow();
                Assert.Throws <InvalidOperationException>(() => ExecutionContext.SuppressFlow());

                ThreadTestHelpers.RunTestInBackgroundThread(() =>
                {
                    ExecutionContext.SuppressFlow();
                    Assert.Throws <InvalidOperationException>(() => asyncFlowControl.Undo());
                    Assert.Throws <InvalidOperationException>(() => asyncFlowControl.Dispose());
                    ExecutionContext.RestoreFlow();
                });

                asyncFlowControl.Undo();
                Assert.Throws <InvalidOperationException>(() => asyncFlowControl.Undo());
                Assert.Throws <InvalidOperationException>(() => asyncFlowControl.Dispose());

                // Changing an async local value does not prevent undoing a flow-suppressed execution context. In .NET Core, the
                // execution context is immutable, so changing an async local value changes the execution context instance,
                // contrary to the .NET Framework.
                asyncFlowControl = ExecutionContext.SuppressFlow();
                asyncLocal.Value = 2;
                asyncFlowControl.Undo();
                VerifyExecutionContextFlow(asyncLocal, 2);
                asyncFlowControl = ExecutionContext.SuppressFlow();
                asyncLocal.Value = 3;
                asyncFlowControl.Dispose();
                VerifyExecutionContextFlow(asyncLocal, 3);
                ExecutionContext.SuppressFlow();
                asyncLocal.Value = 4;
                ExecutionContext.RestoreFlow();
                VerifyExecutionContextFlow(asyncLocal, 4);

                // An async flow control cannot be undone when a different execution context is applied. The .NET Framework
                // mutates the execution context when its state changes, and only changes the instance when an execution context
                // is applied (for instance, through ExecutionContext.Run). The framework prevents a suppressed-flow execution
                // context from being applied by returning null from ExecutionContext.Capture, so the only type of execution
                // context that can be applied is one whose flow is not suppressed. After suppressing flow and changing an async
                // local's value, the .NET Framework verifies that a different execution context has not been applied by
                // checking the execution context instance against the one saved from when flow was suppressed. In .NET Core,
                // since the execution context instance will change after changing the async local's value, it verifies that a
                // different execution context has not been applied, by instead ensuring that the current execution context's
                // flow is suppressed.
                {
                    ExecutionContext executionContext = null;
                    Action verifyCannotUndoAsyncFlowControlAfterChangingExecutionContext =
                        () =>
                    {
                        ExecutionContext.Run(
                            executionContext,
                            state =>
                        {
                            Assert.Throws <InvalidOperationException>(() => asyncFlowControl.Undo());
                            Assert.Throws <InvalidOperationException>(() => asyncFlowControl.Dispose());
                        },
                            null);
                    };

                    executionContext = ExecutionContext.Capture();
                    asyncFlowControl = ExecutionContext.SuppressFlow();
                    verifyCannotUndoAsyncFlowControlAfterChangingExecutionContext();
                    asyncFlowControl.Undo();

                    executionContext = ExecutionContext.Capture();
                    asyncFlowControl = ExecutionContext.SuppressFlow();
                    asyncLocal.Value = 5;
                    verifyCannotUndoAsyncFlowControlAfterChangingExecutionContext();
                    asyncFlowControl.Undo();
                    VerifyExecutionContextFlow(asyncLocal, 5);
                }
            });
        }