public async Task Costs_0_Threads_When_Fuction_Has_Timed_Out_And_CancellationToken_Is_Used()
            {
                var commandIdentifier        = new HystrixCommandIdentifier("group", "key");
                var configurationServiceMock = new Mock <IHystrixConfigurationService>();
                var timeoutWrapper           = new HystrixTimeoutWrapper(commandIdentifier, configurationServiceMock.Object);

                CancellationTokenSource tokenSource = new CancellationTokenSource();

                var primaryTask = new Func <Task <string> >(() => Task.Run(async() =>
                {
                    tokenSource.Token.WaitHandle.WaitOne(2000);
                    await Task.Delay(10, tokenSource.Token);
                    return("a value");
                }));

                configurationServiceMock.Setup(service => service.GetCommandTimeoutInMilliseconds()).Returns(1000);

                int availableThreadsBefore = GetAvailableThreads();

                // act
                await Assert.ThrowsAsync <HystrixTimeoutException>(() => timeoutWrapper.ExecuteAsync(primaryTask, tokenSource));

                int availableThreadsAfter = GetAvailableThreads();

                Assert.Equal(0, availableThreadsBefore - availableThreadsAfter);

                await Task.Delay(2000);

                availableThreadsAfter = GetAvailableThreads();

                Assert.Equal(0, availableThreadsBefore - availableThreadsAfter);
            }
            public void Costs_1_Thread_When_Executing_Within_Timeout()
            {
                var commandIdentifier        = new HystrixCommandIdentifier("group", "key");
                var configurationServiceMock = new Mock <IHystrixConfigurationService>();
                var timeoutWrapper           = new HystrixTimeoutWrapper(commandIdentifier, configurationServiceMock.Object);
                var primaryFunctionMock      = new Mock <Func <string> >();

                primaryFunctionMock.Setup(func => func()).Returns(() =>
                {
                    Thread.Sleep(1000);
                    return("a value");
                });

                configurationServiceMock.Setup(service => service.GetCommandTimeoutInMilliseconds()).Returns(2000);

                int availableThreadsBefore = GetAvailableThreads();

                // act
                Task <string> task = Task.Run(() => timeoutWrapper.Execute(primaryFunctionMock.Object));
                int           availableThreadsDuring = GetAvailableThreads();

                task.Wait();

                Assert.Equal(1, availableThreadsBefore - availableThreadsDuring);
            }
            public async Task Costs_1_Thread_When_Fuction_Has_Timed_Out_But_Isnt_Finished()
            {
                var commandIdentifier        = new HystrixCommandIdentifier("group", "key");
                var configurationServiceMock = new Mock <IHystrixConfigurationService>();
                var timeoutWrapper           = new HystrixTimeoutWrapper(commandIdentifier, configurationServiceMock.Object);
                var primaryTask = new Func <Task <string> >(() => Task.Run(async() =>
                {
                    Thread.Sleep(2000);
                    await Task.Delay(10);
                    return("a value");
                }));


                configurationServiceMock.Setup(service => service.GetCommandTimeoutInMilliseconds()).Returns(1000);

                int availableThreadsBefore = GetAvailableThreads();

                // act
                await Assert.ThrowsAsync <HystrixTimeoutException>(() => timeoutWrapper.ExecuteAsync(primaryTask));

                int availableThreadsAfter = GetAvailableThreads();

                Assert.Equal(1, availableThreadsBefore - availableThreadsAfter);

                await Task.Delay(2000);

                availableThreadsAfter = GetAvailableThreads();

                Assert.Equal(0, availableThreadsBefore - availableThreadsAfter);
            }
            public void Throws_Original_Exception_When_Primary_Function_Throws_Exception()
            {
                var commandIdentifier        = new HystrixCommandIdentifier("group", "key");
                var configurationServiceMock = new Mock <IHystrixConfigurationService>();
                var timeoutWrapper           = new HystrixTimeoutWrapper(commandIdentifier, configurationServiceMock.Object);
                var primaryFunctionMock      = new Mock <Func <string> >();

                primaryFunctionMock.Setup(func => func()).Throws <ArgumentNullException>();

                configurationServiceMock.Setup(service => service.GetCommandTimeoutInMilliseconds()).Returns(5000);

                // act
                Assert.Throws <ArgumentNullException>(() => timeoutWrapper.Execute(primaryFunctionMock.Object));
            }
            public void Runs_The_Primary_Function()
            {
                var commandIdentifier        = new HystrixCommandIdentifier("group", "key");
                var configurationServiceMock = new Mock <IHystrixConfigurationService>();
                var timeoutWrapper           = new HystrixTimeoutWrapper(commandIdentifier, configurationServiceMock.Object);
                var primaryFunction          = new Func <string>(() => "a value");

                configurationServiceMock.Setup(service => service.GetCommandTimeoutInMilliseconds()).Returns(5000);

                // act
                string value = timeoutWrapper.Execute(primaryFunction);

                Assert.Equal("a value", value);
            }
            public async Task Runs_The_Primary_Task()
            {
                var commandIdentifier        = new HystrixCommandIdentifier("group", "key");
                var configurationServiceMock = new Mock <IHystrixConfigurationService>();
                var timeoutWrapper           = new HystrixTimeoutWrapper(commandIdentifier, configurationServiceMock.Object);
                var primaryTask = new Func <Task <string> >(() => Task.FromResult("a value"));

                configurationServiceMock.Setup(service => service.GetCommandTimeoutInMilliseconds()).Returns(5000);

                // act
                string value = await timeoutWrapper.ExecuteAsync(primaryTask);

                Assert.Equal("a value", value);
            }
            public async Task Throws_HystrixTimeoutException_If_Timeout_Is_Exceeded()
            {
                var commandIdentifier        = new HystrixCommandIdentifier("group", "key");
                var configurationServiceMock = new Mock <IHystrixConfigurationService>();
                var timeoutWrapper           = new HystrixTimeoutWrapper(commandIdentifier, configurationServiceMock.Object);
                var primaryTask = new Func <Task <string> >(() => Task.Run(async() =>
                {
                    Thread.Sleep(3000);
                    await Task.Delay(10);
                    return("a value");
                }));

                configurationServiceMock.Setup(service => service.GetCommandTimeoutInMilliseconds()).Returns(50);

                // act
                await Assert.ThrowsAsync <HystrixTimeoutException>(() => timeoutWrapper.ExecuteAsync(primaryTask));
            }
            public void Throws_HystrixTimeoutException_If_Timeout_Is_Exceeded()
            {
                var commandIdentifier        = new HystrixCommandIdentifier("group", "key");
                var configurationServiceMock = new Mock <IHystrixConfigurationService>();
                var timeoutWrapper           = new HystrixTimeoutWrapper(commandIdentifier, configurationServiceMock.Object);
                var primaryFunctionMock      = new Mock <Func <string> >();

                primaryFunctionMock.Setup(func => func()).Returns(() =>
                {
                    Thread.Sleep(5000);
                    return("a value");
                });

                configurationServiceMock.Setup(service => service.GetCommandTimeoutInMilliseconds()).Returns(5);

                // act
                Assert.Throws <HystrixTimeoutException>(() => timeoutWrapper.Execute(primaryFunctionMock.Object));
            }
            public async Task Costs_1_Thread_When_Executing_Within_Timeout()
            {
                var commandIdentifier        = new HystrixCommandIdentifier("group", "key");
                var configurationServiceMock = new Mock <IHystrixConfigurationService>();
                var timeoutWrapper           = new HystrixTimeoutWrapper(commandIdentifier, configurationServiceMock.Object);
                var primaryTask = new Func <Task <string> >(() => Task.Run(async() =>
                {
                    Thread.Sleep(1000);
                    await Task.Delay(10);
                    return("a value");
                }));

                configurationServiceMock.Setup(service => service.GetCommandTimeoutInMilliseconds()).Returns(2000);

                int availableThreadsBefore = GetAvailableThreads();

                // act
                Task <string> task = timeoutWrapper.ExecuteAsync(primaryTask);
                int           availableThreadsDuring = GetAvailableThreads();

                await task;

                Assert.Equal(1, availableThreadsBefore - availableThreadsDuring);
            }