void ExecuteStep(IChannelHandlerContext context, TestScenarioStep currentStep) { if (!context.Channel.Open) { // todo: dispose scheduled work in case of channel closure instead? return; } Task lastTask = null; object lastMessage = null; foreach (object message in currentStep.Messages) { lastMessage = message; var writeTimeoutCts = new CancellationTokenSource(); Task task = context.WriteAsync(message); object timeoutExcMessage = message; context.Channel.EventLoop.Schedule( () => this.completion.TrySetException(new TimeoutException(string.Format("Sending of message did not complete in time: {0}", timeoutExcMessage))), this.sendTimeout, writeTimeoutCts.Token); task.ContinueWith( t => writeTimeoutCts.Cancel(), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously); task.OnFault(t => this.completion.TrySetException(t.Exception)); lastTask = task; } if (currentStep.WaitForFeedback) { if (this.responseTimeout > TimeSpan.Zero) { this.responseTimeoutCts = new CancellationTokenSource(); if (lastTask == null) { this.ScheduleReadTimeoutCheck(context, null); } else { lastTask.ContinueWith( t => this.ScheduleReadTimeoutCheck(context, lastMessage), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously); } } } context.Flush(); if (!currentStep.WaitForFeedback) { context.Channel.EventLoop.Execute( ctx => this.ContinueScenarioExecution((IChannelHandlerContext)ctx), context); } }
void ExecuteStep(IChannelHandlerContext context, TestScenarioStep currentStep) { if (!context.Channel.Open) { // todo: dispose scheduled work in case of channel closure instead? return; } Task lastTask = null; object lastMessage = null; foreach (object message in currentStep.Messages) { lastMessage = message; var writeTimeoutCts = new CancellationTokenSource(); Task task = context.WriteAsync(message); object timeoutExcMessage = message; context.Channel.EventLoop.ScheduleAsync( () => this.completion.TrySetException(new TimeoutException(string.Format("Sending of message did not complete in time: {0}", timeoutExcMessage))), this.sendTimeout, writeTimeoutCts.Token); task.ContinueWith( t => writeTimeoutCts.Cancel(), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously); task.OnFault(t => this.completion.TrySetException(t.Exception)); lastTask = task; } if (currentStep.WaitForFeedback) { if (this.responseTimeout > TimeSpan.Zero) { this.responseTimeoutCts = new CancellationTokenSource(); if (lastTask == null) { this.ScheduleReadTimeoutCheck(context, null); } else { lastTask.ContinueWith( t => this.ScheduleReadTimeoutCheck(context, lastMessage), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously); } } } context.Flush(); if (!currentStep.WaitForFeedback) { context.Channel.EventLoop.Execute( ctx => this.ContinueScenarioExecution((IChannelHandlerContext)ctx), context); } }
void ContinueScenarioExecution(IChannelHandlerContext context) { if (!this.testScenario.MoveNext()) { context.CloseAsync() .ContinueWith( t => this.completion.TrySetException(t.Exception), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously); this.completion.TryComplete(); return; } TestScenarioStep currentStep = this.testScenario.Current; if (currentStep.Delay > TimeSpan.Zero) { context.Channel.EventLoop.Schedule((ctx, state) => this.ExecuteStep((IChannelHandlerContext)ctx, (TestScenarioStep)state), context, currentStep, currentStep.Delay); } else { this.ExecuteStep(context, currentStep); } }