public async Task It_Cancels_Previous()
        {
            var tasks = new List <TaskCompletionSource <object> >();

            var testStrategy = new TestCommandStrategy(onExecute: async(ct, _, __) =>
            {
                var newTask = new TaskCompletionSource <object>();

                tasks.Add(newTask);

                using (ct.Register(() => newTask.TrySetCanceled()))
                {
                    await newTask.Task;
                }
            });

            var strategy = new CancelPreviousCommandStrategy()
            {
                InnerStrategy = testStrategy
            };

            var command = new DynamicCommand(DefaultCommandName, strategy);

            // Start a first execution
            var firstExecution = command.Execute();
            var firstTask      = tasks.ElementAt(0);

            firstTask.Task.IsCanceled.Should().BeFalse();

            // Start a second execution
            var secondExecution = command.Execute();
            var secondTask      = tasks.ElementAt(1);

            firstTask.Task.IsCanceled.Should().BeTrue();
            secondTask.Task.IsCanceled.Should().BeFalse();

            // Start a third execution
            var thirdExecution = command.Execute();
            var thirdTask      = tasks.ElementAt(2);

            secondTask.Task.IsCanceled.Should().BeTrue();
            thirdTask.Task.IsCanceled.Should().BeFalse();

            // Complete the third execution
            thirdTask.TrySetResult(null);

            await Task.WhenAll(firstExecution, secondExecution, thirdExecution);
        }
コード例 #2
0
        public async Task It_Executes_Multiple_In_Parallel()
        {
            var actualExecutions = 0;

            var tasks = new[]
            {
                new TaskCompletionSource <object>(),
                new TaskCompletionSource <object>(),
                new TaskCompletionSource <object>(),
                new TaskCompletionSource <object>(),
            };

            var strategy = new TestCommandStrategy(
                onExecute: async(_, i, ___) =>
            {
                actualExecutions++;

                await tasks[(int)i].Task;
            }
                );

            var command = new DynamicCommand(DefaultCommandName, strategy);

            var executions = tasks
                             .Select((t, i) => command.Execute(i))
                             .ToArray();

            Array.ForEach(tasks, t => t.TrySetResult(null));

            await Task.WhenAll(executions);

            actualExecutions.Should().Be(tasks.Length);
        }
コード例 #3
0
        public async Task It_Catches_Errors_If_Any()
        {
            var exception         = new MyCustomException();
            var receivedCommand   = default(IDynamicCommand);
            var receivedException = default(Exception);

            var testStrategy = new TestCommandStrategy(
                onExecute: (_, __, ___) => throw exception
                );

            var strategy = new ErrorHandlerCommandStrategy(new DynamicCommandErrorHandler((ct, c, e) =>
            {
                receivedCommand   = c;
                receivedException = e;

                return(Task.CompletedTask);
            }))
            {
                InnerStrategy = testStrategy
            };

            var command = new DynamicCommand(DefaultCommandName, strategy);

            await command.Execute();

            receivedCommand.Should().Be(command);
            receivedException.Should().Be(exception);
        }
コード例 #4
0
        public async Task It_Raises_IsExecutingChanged()
        {
            var receivedValues = new List <(object, string, bool)>();

            var strategy = new TestCommandStrategy();
            var command  = new DynamicCommand(DefaultCommandName, strategy);

            command.PropertyChanged += OnPropertyChanged;

            await command.Execute();

            receivedValues.Count().Should().Be(2);

            receivedValues[0].Item1.Should().Be(command);
            receivedValues[0].Item2.Should().Be(nameof(DynamicCommand.IsExecuting));
            receivedValues[0].Item3.Should().Be(true);

            receivedValues[1].Item1.Should().Be(command);
            receivedValues[1].Item2.Should().Be(nameof(DynamicCommand.IsExecuting));
            receivedValues[1].Item3.Should().Be(false);

            void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                receivedValues.Add((sender, e.PropertyName, command.IsExecuting));
            }
        }
コード例 #5
0
        public async Task It_Executes_Without_Parameter()
        {
            var isExecuted = false;

            var strategy = new ActionCommandStrategy(() => isExecuted = true);
            var command  = new DynamicCommand(DefaultCommandName, strategy);

            await command.Execute();

            isExecuted.Should().BeTrue();
        }
コード例 #6
0
        public async Task It_Executes_Strategy()
        {
            var isExecuted = false;

            var strategy = new TestCommandStrategy(
                onExecute: async(_, __, ___) => isExecuted = true
                );

            var command = new DynamicCommand(DefaultCommandName, strategy);

            await command.Execute();

            isExecuted.Should().BeTrue();
        }
コード例 #7
0
        public async Task It_Doesnt_Execute_Strategy_When_CantExecute()
        {
            var isExecuted = false;

            var strategy = new TestCommandStrategy(
                onCanExecute: (_, __) => false,
                onExecute: async(_, __, ___) => isExecuted = true
                );

            var command = new DynamicCommand(DefaultCommandName, strategy);

            await command.Execute();

            isExecuted.Should().BeFalse();
        }
コード例 #8
0
        public async Task It_Executes_With_Parameter_T()
        {
            var executeStrategyParameter = default(TestParameter);

            var strategy = new ActionCommandStrategy <TestParameter>(
                execute: p => executeStrategyParameter = p
                );

            var command = new DynamicCommand(DefaultCommandName, strategy);

            var parameter = new TestParameter();
            await command.Execute(parameter);

            executeStrategyParameter.Should().Be(parameter);
        }
コード例 #9
0
        public async Task It_Executes_Without_Parameter()
        {
            var isExecuted = false;

            var strategy = new TaskCommandStrategy(ct =>
            {
                isExecuted = true;

                return(Task.CompletedTask);
            });

            var command = new DynamicCommand(DefaultCommandName, strategy);

            await command.Execute();

            isExecuted.Should().BeTrue();
        }
コード例 #10
0
        public async Task It_Sends_Parameter_To_Strategy()
        {
            var canExecuteStrategyParameter = default(object);
            var executeStrategyParameter    = default(object);

            var strategy = new TestCommandStrategy(
                onCanExecute: (p, __) => { canExecuteStrategyParameter = p; return(true); },
                onExecute: async(_, p, ___) => executeStrategyParameter = p
                );

            var command = new DynamicCommand(DefaultCommandName, strategy);

            var parameter = new object();
            await command.Execute(parameter);

            canExecuteStrategyParameter.Should().Be(parameter);
            executeStrategyParameter.Should().Be(parameter);
        }
コード例 #11
0
        public async Task It_Stays_Executing_When_Multiple_Executions()
        {
            var receivedValues = new List <(object, bool)>();

            var tasks = new[]
            {
                new TaskCompletionSource <object>(),
                new TaskCompletionSource <object>(),
                new TaskCompletionSource <object>(),
                new TaskCompletionSource <object>(),
            };

            var strategy = new TestCommandStrategy(
                onExecute: async(_, i, ___) =>
            {
                await tasks[(int)i].Task;
            }
                );

            var command = new DynamicCommand(DefaultCommandName, strategy);

            command.IsExecutingChanged += OnIsExecutingChanged;

            var executions = tasks
                             .Select((t, i) => command.Execute(i))
                             .ToArray();

            Array.ForEach(tasks, t => t.TrySetResult(null));

            await Task.WhenAll(executions);

            receivedValues.Count().Should().Be(2);

            receivedValues[0].Item1.Should().Be(command);
            receivedValues[0].Item2.Should().Be(true);

            receivedValues[1].Item1.Should().Be(command);
            receivedValues[1].Item2.Should().Be(false);

            void OnIsExecutingChanged(object sender, EventArgs e)
            {
                receivedValues.Add((sender, command.IsExecuting));
            }
        }
コード例 #12
0
        public async Task It_Has_Single_Execution()
        {
            var concurrentExecutions    = 0;
            var hadConcurrentExecutions = false;

            var tasks = new[]
            {
                new TaskCompletionSource <object>(),
                new TaskCompletionSource <object>(),
                new TaskCompletionSource <object>(),
                new TaskCompletionSource <object>(),
            };

            var testStrategy = new TestCommandStrategy(onExecute: async(_, i, ___) =>
            {
                if (Interlocked.Increment(ref concurrentExecutions) > 1)
                {
                    hadConcurrentExecutions = true;
                }

                await tasks[(int)i].Task;

                Interlocked.Decrement(ref concurrentExecutions);
            });

            var strategy = new LockCommandStrategy()
            {
                InnerStrategy = testStrategy
            };

            var command = new DynamicCommand(DefaultCommandName, strategy);

            var executions = tasks
                             .Select((t, i) => command.Execute(i))
                             .ToArray();

            Array.ForEach(tasks, t => t.TrySetResult(null));

            await Task.WhenAll(executions);

            hadConcurrentExecutions.Should().BeFalse();
        }
コード例 #13
0
        public async Task It_Executes_With_Parameter_T()
        {
            var executeStrategyParameter = default(TestParameter);

            var strategy = new TaskCommandStrategy <TestParameter>(
                execute: (ct, p) =>
            {
                executeStrategyParameter = p;

                return(Task.CompletedTask);
            }
                );

            var command = new DynamicCommand(DefaultCommandName, strategy);

            var parameter = new TestParameter();
            await command.Execute(parameter);

            executeStrategyParameter.Should().Be(parameter);
        }
コード例 #14
0
        public async Task It_Disables_While_Executing()
        {
            var taskCompletionSource = new TaskCompletionSource <object>();

            var testStrategy = new TestCommandStrategy(
                onExecute: (_, __, ___) => taskCompletionSource.Task
                );

            var strategy = new DisableWhileExecutingCommandStrategy()
            {
                InnerStrategy = testStrategy
            };

            var command = new DynamicCommand(DefaultCommandName, strategy);

            command.CanExecuteChanged += OnCanExecuteChanged;

            var canExecute = command.CanExecute(null);

            // The command should be enabled
            canExecute.Should().BeTrue();

            // We execute the command
            var commandExecution = command.Execute();

            // The command should be disabled
            canExecute.Should().BeFalse();

            // The command completes
            taskCompletionSource.TrySetResult(null);

            await commandExecution;

            // The command should be enabled
            canExecute.Should().BeTrue();

            void OnCanExecuteChanged(object sender, EventArgs e)
            {
                canExecute = command.CanExecute(null);
            }
        }
コード例 #15
0
        public async Task It_Awaits_Execution()
        {
            var taskCompletionSource = new TaskCompletionSource <object>();

            var strategy = new TestCommandStrategy(
                onExecute: async(_, __, ___) =>
            {
                await taskCompletionSource.Task;
            }
                );

            var command = new DynamicCommand(DefaultCommandName, strategy);

            var commandExecution = command.Execute();

            taskCompletionSource.TrySetResult(null);

            await commandExecution;

            taskCompletionSource.Task.IsCompleted.Should().BeTrue();
        }
コード例 #16
0
        public async Task It_Observes_IsExecuting()
        {
            var receivedValues = new List <bool>();
            var strategy       = new TestCommandStrategy();

            var command = new DynamicCommand(DefaultCommandName, strategy);

            var testSubscriber = new TestSubscriber <bool>(onNext: t => receivedValues.Add(t));

            var subscription = command
                               .ObserveIsExecuting()
                               .Subscribe(testSubscriber);

            using (subscription)
            {
                await command.Execute();

                receivedValues.Count().Should().Be(2);
                receivedValues[0].Should().BeTrue();
                receivedValues[1].Should().BeFalse();
            }
        }
コード例 #17
0
        public async Task It_Doesnt_Catch_Errors_If_None()
        {
            var catchedErrors = false;

            var testStrategy = new TestCommandStrategy();

            var strategy = new ErrorHandlerCommandStrategy(new DynamicCommandErrorHandler((ct, c, e) =>
            {
                catchedErrors = true;

                return(Task.CompletedTask);
            }))
            {
                InnerStrategy = testStrategy
            };

            var command = new DynamicCommand(DefaultCommandName, strategy);

            await command.Execute();

            catchedErrors.Should().BeFalse();
        }
コード例 #18
0
        public async Task It_Cancels_CancellationToken_When_Disposed()
        {
            var taskCompletionSource = new TaskCompletionSource <object>();

            var strategy = new TestCommandStrategy(
                onExecute: async(ct, _, __) =>
            {
                using (ct.Register(() => taskCompletionSource.TrySetCanceled()))
                {
                    await taskCompletionSource.Task;
                }
            }
                );

            var command = new DynamicCommand(DefaultCommandName, strategy);

            var commandExecution = command.Execute();

            command.Dispose();

            await commandExecution;

            taskCompletionSource.Task.IsCanceled.Should().BeTrue();
        }
コード例 #19
0
        public async Task It_Executes_On_Background_Thread()
        {
            var isRunningOnThreadPool = false;

            var testStrategy = new TestCommandStrategy(
                onExecute: (_, __, ___) =>
            {
                isRunningOnThreadPool = Thread.CurrentThread.IsThreadPoolThread;

                return(Task.CompletedTask);
            }
                );

            var strategy = new BackgroundCommandStrategy()
            {
                InnerStrategy = testStrategy
            };

            var command = new DynamicCommand(DefaultCommandName, strategy);

            await command.Execute();

            isRunningOnThreadPool.Should().BeTrue();
        }