コード例 #1
0
        public void ForceUpdateDynamicState_ConcurrentCalls_AllCallsMakeChanges()
        {
            var testTimeout        = TimeSpan.FromSeconds(30);
            var destinationManager = new Mock <IDestinationManager>();
            var itemsCalled        = new SemaphoreSlim(0);

            destinationManager.SetupGet(d => d.Items).Returns(() =>
            {
                itemsCalled.Wait();
                return(new DestinationInfo[0]);
            });
            var destManagerfactory = new Mock <IDestinationManagerFactory>();

            destManagerfactory.Setup(f => f.CreateDestinationManager()).Returns(destinationManager.Object);
            var clusterManager = new ClusterManager(destManagerfactory.Object, Array.Empty <IClusterChangeListener>());
            var cluster        = clusterManager.GetOrCreateItem("cluster0", c => EnableHealthChecks(c));

            var taskCount       = Environment.ProcessorCount * 2;
            var concurrentTasks = Enumerable.Repeat(0, taskCount)
                                  .Select(_ => Task.Factory.StartNew(() => cluster.ForceUpdateDynamicState(), TaskCreationOptions.RunContinuationsAsynchronously))
                                  .ToArray();

            itemsCalled.Release(taskCount);

            // Assert all concurrent tasks complete without a call to DestinationManager.Items getter.
            Assert.True(Task.WaitAll(concurrentTasks, testTimeout));

            destinationManager.VerifyGet(d => d.Items, Times.Exactly(taskCount));
            destinationManager.VerifyNoOtherCalls();
        }
コード例 #2
0
        public void UpdateDynamicState_ConcurrentCalls_FirstAndLastCallsMakeChanges()
        {
            var testTimeout        = TimeSpan.FromSeconds(30);
            var destinationManager = new Mock <IDestinationManager>();
            var itemsCalled        = new AutoResetEvent(false);
            var returnItems        = new ManualResetEvent(false);

            destinationManager.SetupGet(d => d.Items).Returns(() =>
            {
                itemsCalled.Set();
                returnItems.WaitOne();
                return(new DestinationInfo[0]);
            });
            var destManagerfactory = new Mock <IDestinationManagerFactory>();

            destManagerfactory.Setup(f => f.CreateDestinationManager()).Returns(destinationManager.Object);
            var clusterManager = new ClusterManager(destManagerfactory.Object, Array.Empty <IClusterChangeListener>());
            var cluster        = clusterManager.GetOrCreateItem("cluster0", c => EnableHealthChecks(c));

            var mainTask = Task.Factory.StartNew(() => cluster.UpdateDynamicState(), TaskCreationOptions.RunContinuationsAsynchronously);

            Assert.True(itemsCalled.WaitOne(testTimeout));

            var allTaskCount       = Environment.ProcessorCount * 2;
            var pendingTasks       = allTaskCount;
            var allButOneCompleted = new ManualResetEventSlim(false);
            var concurrentTasks    = Enumerable.Repeat(0, allTaskCount)
                                     .Select(_ => Task.Factory.StartNew(() =>
            {
                cluster.UpdateDynamicState();
                if (Interlocked.Decrement(ref pendingTasks) == 1)
                {
                    allButOneCompleted.Set();
                }
            }, TaskCreationOptions.RunContinuationsAsynchronously))
                                     .ToArray();

            Assert.True(allButOneCompleted.Wait(testTimeout));
            returnItems.Set();

            // Assert all concurrent tasks complete without a call to DestinationManager.Items getter.
            Assert.True(Task.WaitAll(concurrentTasks, testTimeout));
            Assert.Equal(0, Volatile.Read(ref pendingTasks));

            // Assert the main task that acquired the ClusterInfo lock completes.
            Assert.True(mainTask.Wait(testTimeout));

            destinationManager.VerifyGet(d => d.Items, Times.Exactly(2));
            destinationManager.VerifyNoOtherCalls();
        }