public async Task CheckStaleIntervalTests()
        {
            var activityId = Guid.NewGuid().ToString();
            var workerInfo = new MockWorkerInfo();
            var settings   = new ScaleSettings
            {
                StaleWorkerCheckInterval = TimeSpan.FromMilliseconds(500)
            };

            using (var scaleManager = new MockScaleManager(MockBehavior.Strict, settings))
            {
                // Setup
                scaleManager.MockWorkerTable.Setup(t => t.List())
                .Returns(Task.FromResult(Enumerable.Empty <IWorkerInfo>()));
                scaleManager.MockScaleTracer.Setup(t => t.TraceInformation(activityId, workerInfo, It.IsAny <string>()));

                // Test
                for (int i = 0; i < 10; ++i)
                {
                    await scaleManager.MockCheckStaleWorker(activityId, workerInfo);

                    await Task.Delay(100);
                }

                // Assert
                scaleManager.MockWorkerTable.Verify(t => t.List(), Times.AtLeast(1));
                scaleManager.MockWorkerTable.Verify(t => t.List(), Times.AtMost(4));
            }
        }
        public async Task SuccessfulSetTests(IWorkerInfo worker, IWorkerInfo current)
        {
            var activityId = Guid.NewGuid().ToString();
            var tableLock  = new MockWorkerTableLock();

            // Test
            using (var scaleManager = new MockScaleManager(MockBehavior.Strict))
            {
                // Setup
                scaleManager.MockWorkerTable.Setup(t => t.AcquireLock())
                .Returns(() => tableLock.AcquireLock());
                scaleManager.MockWorkerTable.Setup(t => t.GetManager())
                .Returns(Task.FromResult(current));
                scaleManager.MockWorkerTable.Setup(t => t.SetManager(worker))
                .Returns(Task.CompletedTask);
                scaleManager.MockScaleTracer.Setup(t => t.TraceInformation(activityId, worker, It.Is <string>(c => c.Contains("Acquire table lock"))));
                scaleManager.MockScaleTracer.Setup(t => t.TraceInformation(activityId, worker, It.Is <string>(c => c.Contains("Release table lock"))));
                scaleManager.MockScaleTracer.Setup(t => t.TraceInformation(activityId, worker, It.Is <string>(c => c.Contains("is set to be a manager"))));

                // test
                var newManager = await scaleManager.MockSetManager(activityId, worker, current);

                // assert
                scaleManager.VerifyAll();
                Assert.True(ScaleUtils.Equals(newManager, worker));
                Assert.False(ScaleUtils.Equals(newManager, current));
            }
        }
        public async Task PingWorkerIntervalTests()
        {
            var activityId = Guid.NewGuid().ToString();
            var workerInfo = new MockWorkerInfo();
            var settings   = new ScaleSettings
            {
                WorkerPingInterval = TimeSpan.FromMilliseconds(500)
            };

            using (var scaleManager = new MockScaleManager(MockBehavior.Strict, settings))
            {
                // Setup
                scaleManager.MockScaleHandler.Setup(h => h.PingWorker(activityId, workerInfo))
                .Returns(Task.FromResult(true));
                scaleManager.MockWorkerTable.Setup(t => t.AddOrUpdate(workerInfo))
                .Returns(Task.CompletedTask);
                scaleManager.MockScaleTracer.Setup(t => t.TraceUpdateWorker(activityId, workerInfo, It.Is <string>(s => s.Contains("updated"))));

                var loop = 10;
                for (int i = 0; i < loop; ++i)
                {
                    // test
                    await scaleManager.MockPingWorker(activityId, workerInfo);

                    await Task.Delay(100);
                }

                // assert
                scaleManager.VerifyAll();
                scaleManager.MockScaleHandler.Verify(h => h.PingWorker(activityId, workerInfo), Times.Between(2, loop - 1, Range.Inclusive));
                scaleManager.MockWorkerTable.Verify(t => t.AddOrUpdate(workerInfo), Times.Exactly(loop));
                scaleManager.MockScaleTracer.Verify(t => t.TraceUpdateWorker(activityId, workerInfo, It.Is <string>(s => s.Contains("updated"))), Times.Exactly(loop));
            }
        }
        public async Task BasicTests(IWorkerInfo manager, IWorkerInfo toRemove)
        {
            var activityId = Guid.NewGuid().ToString();

            // Test
            using (var scaleManager = new MockScaleManager(MockBehavior.Strict))
            {
                scaleManager.MockScaleHandler.Setup(s => s.RemoveWorker(activityId, toRemove))
                .Returns(Task.CompletedTask);
                scaleManager.MockWorkerTable.Setup(t => t.Delete(toRemove))
                .Returns(Task.CompletedTask);
                scaleManager.MockScaleTracer.Setup(t => t.TraceRemoveWorker(activityId, toRemove, It.Is <string>(s => s.Contains(manager.ToDisplayString()))));

                // test
                await scaleManager.MockRequestRemoveWorker(activityId, manager, toRemove);

                // assert
                scaleManager.VerifyAll();
            }
        }
        public async Task ValidWorkerTests()
        {
            var activityId = Guid.NewGuid().ToString();
            var workerInfo = new MockWorkerInfo();

            // Test
            using (var scaleManager = new MockScaleManager(MockBehavior.Strict))
            {
                // Setup
                scaleManager.MockScaleHandler.Setup(h => h.PingWorker(activityId, workerInfo))
                .Returns(Task.FromResult(true));
                scaleManager.MockWorkerTable.Setup(t => t.AddOrUpdate(workerInfo))
                .Returns(Task.CompletedTask);
                scaleManager.MockScaleTracer.Setup(t => t.TraceUpdateWorker(activityId, workerInfo, It.Is <string>(s => s.Contains("updated"))));

                // test
                await scaleManager.MockPingWorker(activityId, workerInfo);

                // assert
                scaleManager.VerifyAll();
            }
        }
        public async Task BasicTests(int maxWorkers, IEnumerable <IWorkerInfo> workers, IWorkerInfo manager, bool force, bool expected)
        {
            var activityId = Guid.NewGuid().ToString();
            var settings   = new ScaleSettings {
                MaxWorkers = maxWorkers
            };

            // Test
            using (var scaleManager = new MockScaleManager(MockBehavior.Strict, settings))
            {
                if (expected)
                {
                    scaleManager.MockScaleTracer.Setup(t => t.TraceAddWorker(activityId, manager, It.IsAny <string>()));

                    scaleManager.MockScaleHandler.Setup(s => s.AddWorker(activityId, It.IsAny <IEnumerable <string> >(), It.IsAny <int>()))
                    .Returns(Task.FromResult("3"));
                }
                else
                {
                    scaleManager.MockScaleTracer.Setup(t => t.TraceWarning(activityId, manager, It.IsAny <string>()));

                    if (force || workers.Count() < settings.MaxWorkers)
                    {
                        scaleManager.MockScaleHandler.Setup(s => s.AddWorker(activityId, It.IsAny <IEnumerable <string> >(), It.IsAny <int>()))
                        .Returns(Task.FromResult(string.Empty));
                    }
                }

                // test
                var actual = await scaleManager.MockRequestAddWorker(activityId, workers, manager, force);

                // assert
                scaleManager.VerifyAll();
                Assert.Equal(expected, actual);
            }
        }
        public async Task InvalidWorkerTests()
        {
            var activityId = Guid.NewGuid().ToString();
            var workerInfo = new MockWorkerInfo();

            // Test
            using (var scaleManager = new MockScaleManager(MockBehavior.Strict))
            {
                // Setup
                scaleManager.MockScaleHandler.Setup(h => h.PingWorker(activityId, workerInfo))
                .Returns(Task.FromResult(false));
                scaleManager.MockWorkerTable.Setup(t => t.Delete(workerInfo))
                .Returns(Task.CompletedTask);
                scaleManager.MockScaleTracer.Setup(t => t.TraceWarning(activityId, workerInfo, It.Is <string>(s => s.Contains("not belong"))));
                scaleManager.MockScaleTracer.Setup(t => t.TraceRemoveWorker(activityId, workerInfo, It.Is <string>(s => s.Contains("removed"))));

                // test
                var exception = await Assert.ThrowsAsync <InvalidOperationException>(async() => await scaleManager.MockPingWorker(activityId, workerInfo));

                // assert
                Assert.Contains("not belong", exception.Message);
                scaleManager.VerifyAll();
            }
        }