예제 #1
0
        public override void RunTest(ISyncLock lockObject, TestParameters testParameters)
        {
            if (lockObject is NoOpLock)
            {
                throw new InapplicableTestException("Unbalanced calls test not applicable for this lock type");
            }

            Console.WriteLine("Normal usage scenario -- autolock create / dispose with using");

            ExerciseStandardUsage(lockObject, false);

            Console.WriteLine("Normal usage scenario -- succeeded");

            Console.WriteLine("Exception in using -- lock should be freed");

            try
            {
                ExerciseStandardUsage(lockObject, true);
            }
            catch (IntentionalTestException e)
            {
                Console.WriteLine("Expected exception caught: {0}: {1}", e.GetType().ToString(), e.Message);
            }

            Console.WriteLine("Validate that the lock is freed by exercising the normal scenario again");

            ExerciseStandardUsage(lockObject, false);
        }
예제 #2
0
        public override void RunTest(ISyncLock syncLock, TestParameters testParameters)
        {
            this.syncLock = (ISyncLock)syncLock;

            requireLock = !(syncLock is NoOpLock);

            testTimeoutSeconds = testParameters.MaxWaitSeconds;

            Thread[] threads = new Thread[desiredValues.Length];

            for (int threadIndex = 0; threadIndex < threads.Length; threadIndex++)
            {
                threads[threadIndex] = new Thread(ContendingThreadFunction);

                completedEvents[threadIndex] = new ManualResetEvent(false);

                threads[threadIndex].Start(threadIndex);
            }

            startThreadsEvent.Set();

            Console.WriteLine("Sleeping for {0} seconds", testParameters.MaxWaitSeconds);

            Thread.Sleep(testParameters.MaxWaitSeconds * 1000);

            Console.WriteLine("Signaling threads to terminate");

            endTestEvent.Set();

            Console.WriteLine("Waiting for {0} threads to complete after termination signal", threads.Length);

            WaitHandle.WaitAll(completedEvents);

            Console.WriteLine("Completed all waits for thread ids:");

            for (int threadIndex = 0; threadIndex < threads.Length; threadIndex++)
            {
                Console.WriteLine("Thread: {0}\tIterations: {1}", threads[threadIndex].ManagedThreadId, iterationCounts[threadIndex]);
            }

            if (!requireLock)
            {
                if (!expectedSynchronizationErrorOccurred)
                {
                    throw new InvalidOperationException("Expected synchronization error due to absence of lock did not occur.");
                }

                Console.WriteLine("Expected synchronization error successfully detected.");
            }
            else if (null != testException)
            {
                throw testException;
            }
        }
예제 #3
0
        void ExerciseStandardUsage(ISyncLock lockObject, bool throwException)
        {
            using (AutoLock.Lock(lockObject))
            {
                Console.WriteLine("Inside autolock block");

                if (throwException)
                {
                    Console.WriteLine("Testing exception thrown in autolock block -- will now throw exception");

                    throw new IntentionalTestException("Intentional exception thrown inside of an autolock block");
                }
            }

            InvalidOperationException unlockException = null;

            Console.WriteLine("Validate that the lock is correctly unlocked after exiting using block");

            try
            {
                lockObject.Unlock();
            }
            catch (InvalidOperationException e)
            {
                unlockException = e;
            }

            if (unlockException != null)
            {
                Console.WriteLine("Caught expected exception from unlocking an unlocked object");
            }
            else
            {
                throw new InvalidOperationException("Failed to get exception in unlocking unlocked object after an autolock was exited");
            }
        }
예제 #4
0
        public override void RunTest(ISyncLock lockObject, TestParameters testParameters)
        {
            if (lockObject is NoOpLock)
            {
                throw new InapplicableTestException("Unbalanced calls test not applicable for this lock type");
            }

            ISyncLock syncLock = (ISyncLock)lockObject;

            Exception releaseUnlockedException = null;

            Console.WriteLine("Trying unlock with no lock -- this should fail");

            try
            {
                syncLock.Unlock();
            }
            catch (InvalidOperationException e)
            {
                Console.WriteLine("Caught expected InvalidOperationException");
                releaseUnlockedException = e;
            }

            Console.WriteLine("Lock / unlock succeeded");

            if (releaseUnlockedException == null)
            {
                throw new InvalidOperationException("Unlock of already unlocked lock should not have succeeded");
            }

            Console.WriteLine("Simple lock / unlock -- this should succeed");

            syncLock.Lock();
            syncLock.Unlock();

            Console.WriteLine("Re-entrant lock scenario -- try locking twice -- this should fail for some locks, succeed for others");

            Exception reentrantLockException = null;

            syncLock.Lock();

            try
            {
                Console.WriteLine("Second lock attempt");
                syncLock.Lock();
                Console.WriteLine("Second lock granted");
            }
            catch (InvalidOperationException e)
            {
                Console.WriteLine("Expected InvalidOperationException caught");
                reentrantLockException = e;
            }

            syncLock.Unlock();

            if (syncLock.GetType() == typeof(SimpleSpinLock))
            {
                if (reentrantLockException == null)
                {
                    throw new InvalidOperationException("Lock should not allow re-entrant call to already locked lock");
                }
            }
            else
            {
                Console.WriteLine("Successful re-entrant lock with lock count 2, now perform extra unlock");

                syncLock.Unlock();

                Console.WriteLine("Successfully performed second unlock");

                VerifyUnlocked(syncLock);
            }

            // Now test higher scale re-entrance

            Console.WriteLine("Testing locking {0} times on the same thread, then unlocking the same #", lockMax);

            if (!(syncLock is SimpleSpinLock))
            {
                for (int lockCount = 0; lockCount < lockMax; lockCount++)
                {
                    syncLock.Lock();
                }

                for (int unlockCount = 0; unlockCount < lockMax; unlockCount++)
                {
                    syncLock.Unlock();
                }

                VerifyUnlocked(syncLock);
            }

            Console.WriteLine("Successfully verified lock re-entrance count for non-trivial number of re-entrant calls");

            Console.WriteLine("Lock once, unlock twice -- this should fail");

            syncLock.Lock();
            syncLock.Unlock();

            Exception unbalancedException = null;

            try
            {
                syncLock.Unlock();
            }
            catch (InvalidOperationException e)
            {
                Console.WriteLine("Expected InvalidOperationException caught");

                unbalancedException = e;
            }

            if (unbalancedException == null)
            {
                throw new InvalidOperationException("Lock should not allow unlock to be called twice after one call to lock");
            }
        }
예제 #5
0
        void VerifyUnlocked(ISyncLock syncLock)
        {
            InvalidOperationException tooManyUnlocksException = null;

            try
            {
                syncLock.Unlock();
            }
            catch (InvalidOperationException e)
            {
                Console.WriteLine("Caught expected exception after unlocking too many times: {0}: {1}", e.GetType().ToString(), e.Message);
                tooManyUnlocksException = e;
            }

            if (tooManyUnlocksException == null)
            {
                throw new InvalidOperationException("Unlock should not have succeeded after being in what should have been an unlocked state");
            }
        }
예제 #6
0
        void TestLockWait(ISyncLock syncLock, TimeSpan waitBeforeCheckingLock, TimeSpan addtionalTimeBeforeRelease, bool waitForUnlock)
        {
            TimeSpan expectedWaitTime = new TimeSpan((long)(Math.Min(waitBeforeCheckingLock.Ticks, addtionalTimeBeforeRelease.Ticks))) + new TimeSpan(0,0,3);

            lockCheckReadyAcquired.Reset();
            lockReleaseEvent.Reset();
            variationCompleteEvent.Reset();

            lockWaitTime = waitBeforeCheckingLock; // +waitBeforeCheckingLock;
            releaseDelay = addtionalTimeBeforeRelease;

            lockThread = new Thread(LockThreadFunction);

            lockThread.Start(syncLock);

            WaitForLockAcquisition();

            // This should expire

            bool expired = ! syncLock.WaitForLock(new TimeSpan(0,0,0));

            if (! expired)
            {
                throw new InvalidOperationException("Lock was released before expected, due to either lock defect or race conditions that should be rare");
            }

            // Tell the other thread to release the lock
            lockReleaseEvent.Set();

            DateTime waitStart = DateTime.UtcNow;

            if (waitForUnlock)
            {
                WaitForLockRelease();
            }

            bool acquiredLock = syncLock.WaitForLock(lockWaitTime);

            DateTime waitEnd = DateTime.UtcNow;

            variationCompleteEvent.Set();

            if (!acquiredLock)
            {
                if (waitForUnlock || ( waitBeforeCheckingLock > addtionalTimeBeforeRelease) )
                {
                    throw new InvalidOperationException("Unable to acquire lock within the specified timeout");
                }
                else
                {
                    Console.WriteLine("Wait for lock timed out as expected");
                }
            }
            else
            {
                syncLock.Unlock();

                if (waitBeforeCheckingLock < addtionalTimeBeforeRelease)
                {
                    throw new InvalidOperationException("Wait did not time out as expected");
                }
                else
                {
                    Console.WriteLine("Wait was satisfied as expected");
                }
            }

            TimeSpan duration = waitEnd - waitStart;

            Console.WriteLine("Expected wait time was {0} and actual time was {1}", expectedWaitTime, duration);

            if (duration > expectedWaitTime)
            {
                throw new InvalidOperationException(string.Format("Expected wait time was {0} and actual time was {1}", expectedWaitTime, duration));
            }
        }
예제 #7
0
 public abstract void RunTest(ISyncLock lockObject, TestParameters testParameters);
예제 #8
0
 static ObjectLock()
 {
     stateLock = new SimpleSpinLock();
     objectToLockMap = new Dictionary<object, ObjectLock>();
 }