public async Task TestConcurrentCancelFirst()
        {
            var entryContext = AsyncTestContext.Current;
            var sut          = new FastAsyncLock();
            var ct           = new CancellationTokenSource();

            using (var otherThread = new AsyncTestRunner(CommonTwoStepsLock(sut)))
            {
                // Acquire the lock on another async context
                await otherThread.Advance();

                Assert.IsTrue(otherThread.HasLock());

                // Try to acquire the lock from this async context
                entryContext.Validate();
                var locking = sut.LockAsync(CancellationToken.None);
                Assert.AreEqual(TaskStatus.WaitingForActivation, locking.Status);

                // Cancel the CT of the other thread ... this should not impact the awaiter !
                ct.Cancel();
                Assert.AreEqual(TaskStatus.WaitingForActivation, locking.Status);

                // Finally validate that if we release the lock from the other thread, we are still able to acquire the lock
                await otherThread.Advance();

                Assert.AreEqual(TaskStatus.RanToCompletion, locking.Status);
            }
        }
        public async Task TestConcurrentAccess()
        {
            var entryContext = AsyncTestContext.Current;
            var sut          = new FastAsyncLock();

            using (var otherThread = new AsyncTestRunner(CommonTwoStepsLock(sut)))
            {
                // Acquire the lock on another async context
                await otherThread.Advance();

                Assert.IsTrue(otherThread.HasLock());

                // Try to acquire the lock from this async context
                entryContext.Validate();
                var locking = sut.LockAsync(CancellationToken.None);
                Assert.AreEqual(TaskStatus.WaitingForActivation, locking.Status);

                await otherThread.Advance();                                 // Will release the lock

                Assert.AreEqual(TaskStatus.RanToCompletion, locking.Status); // so lock is now acquired (sync)
            }
        }
        public async Task TestConcurrentCancelSecond()
        {
            var entryContext = AsyncTestContext.Current;
            var sut          = new FastAsyncLock();
            var ct           = new CancellationTokenSource();

            using (var otherThread = new AsyncTestRunner(CommonTwoStepsLock(sut)))
            {
                // Acquire the lock on another async context
                await otherThread.Advance();

                Assert.IsTrue(otherThread.HasLock());

                // Try to acquire the lock from this async context
                entryContext.Validate();
                var locking = sut.LockAsync(ct.Token);
                Assert.AreEqual(TaskStatus.WaitingForActivation, locking.Status);

                // But cancel before the other async context completes
                ct.Cancel();
                Assert.AreEqual(TaskStatus.Canceled, locking.Status);
            }
        }