public void TestSynchronizedBlockWithInvalidUsage()
        {
            this.TestWithError(async() =>
            {
                try
                {
                    var monitor = SynchronizedBlock.Lock(new object());
                    // We yield to make sure the execution is asynchronous.
                    await Task.Yield();
                    monitor.Pulse();

                    // We do not dispose inside a using statement, because the `SynchronizationLockException`
                    // will trigger the disposal, which will fail because an await statement is not allowed
                    // inside a synchronized block. The C# compiler normally prevents it when using the lock
                    // statement, but we cannot prevent it when directly using the mock.
                    monitor.Dispose();
                }
                catch (SynchronizationLockException)
                {
                    Specification.Assert(false, "Expected exception thrown.");
                }
            },
                               expectedError: "Expected exception thrown.",
                               replay: true);
        }
 internal void DoLock()
 {
     using (var monitor = SynchronizedBlock.Lock(this.SyncObject))
     {
         Debug.WriteLine("Re-entered lock from the same task {0}.", GetCurrentTaskId());
     }
 }
 internal void Signal()
 {
     using (var monitor = SynchronizedBlock.Lock(this.SyncObject))
     {
         this.Signalled = true;
         monitor.Pulse();
     }
 }
 internal void ReentrantWait()
 {
     Debug.WriteLine("Entering lock on task {0}.", GetCurrentTaskId());
     using (var monitor = SynchronizedBlock.Lock(this.SyncObject))
     {
         Debug.WriteLine("Entered lock on task {0}.", GetCurrentTaskId());
         this.DoWait();
     }
 }
 public void TestSynchronizedBlockWithInvalidSyncObject()
 {
     this.TestWithException <ArgumentNullException>(() =>
     {
         using (var monitor = SynchronizedBlock.Lock(null))
         {
         }
     },
                                                    replay: true);
 }
 internal void DoWait()
 {
     using (var monitor = SynchronizedBlock.Lock(this.SyncObject))
     {
         Debug.WriteLine("Re-entered lock from the same task {0}.", GetCurrentTaskId());
         Debug.WriteLine("Task {0} is now waiting...", GetCurrentTaskId());
         this.Wait();
         Debug.WriteLine("Task {0} received the signal.", GetCurrentTaskId());
     }
 }
 internal void Wait()
 {
     using (var monitor = SynchronizedBlock.Lock(this.SyncObject))
     {
         while (!this.Signalled)
         {
             bool result = monitor.Wait();
             Assert.True(result, "Wait returned false.");
         }
     }
 }
        public void TestSynchronizedBlockWithInvalidPulseAllState()
        {
            this.TestWithException <SynchronizationLockException>(() =>
            {
                SynchronizedBlock monitor;
                using (monitor = SynchronizedBlock.Lock(new object()))
                {
                }

                monitor.PulseAll();
            },
                                                                  replay: true);
        }
        public void TestSynchronizedBlockWithAsyncExecution()
        {
            if (!this.IsSystematicTest)
            {
                return;
            }

            // We only test this without rewriting. With rewriting, we don't need to use synchronized block
            // and the compiler will make sure that an await cannot exist inside a lock block.
            this.TestWithError(async() =>
            {
                using (var monitor = SynchronizedBlock.Lock(new object()))
                {
                    // Normally, an await statement is not allowed inside a synchronized block.
                    // The C# compiler normally prevents it when using the lock statement, but
                    // we cannot prevent it when directly using the mock. Using it here fails
                    // because `Dispose` is invoked from an asynchronized continuation.
                    await Task.Yield();
                }
            },
                               expectedError: "Cannot invoke Dispose without acquiring the lock.",
                               replay: true);
        }