예제 #1
0
        public void TraceBeginEndAsync_Traces_When_Inner_Cancels()
        {
            // Arrange
            TestTraceWriter    traceWriter = new TestTraceWriter();
            HttpRequestMessage request     = new HttpRequestMessage();

            TraceRecord[] expectedTraces = new TraceRecord[]
            {
                new TraceRecord(request, "testCategory", TraceLevel.Info)
                {
                    Kind = TraceKind.Begin, Operator = "tester", Operation = "testOp", Message = "beginMessage"
                },
                new TraceRecord(request, "testCategory", TraceLevel.Warn)
                {
                    Kind = TraceKind.End, Operator = "tester", Operation = "testOp", Message = "errorMessage"
                },
            };

            // Act & Assert
            Assert.Throws <TaskCanceledException>(
                () => traceWriter.TraceBeginEndAsync(request,
                                                     "testCategory",
                                                     TraceLevel.Info,
                                                     "tester",
                                                     "testOp",
                                                     beginTrace: (tr) => { tr.Message = "beginMessage"; },
                                                     execute: () => TaskHelpers.Canceled(),
                                                     endTrace: (tr) => { tr.Message = "won't happen"; },
                                                     errorTrace: (tr) => { tr.Message = "errorMessage"; }).Wait());

            // Assert
            Assert.Equal <TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
        }
예제 #2
0
        public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content,
                                                TransportContext transportContext, CancellationToken cancellationToken)
        {
            if (type == null)
            {
                throw Error.ArgumentNull("type");
            }
            if (writeStream == null)
            {
                throw Error.ArgumentNull("writeStream");
            }
            if (cancellationToken.IsCancellationRequested)
            {
                return(TaskHelpers.Canceled());
            }

            try
            {
                this.WriteToStream(type, value, writeStream, content);
                return(TaskHelpers.Completed());
            }
            catch (Exception e)
            {
                return(TaskHelpers.FromError(e));
            }
        }
        public void ExecuteAsync_IfInnerResultTaskIsCanceled_ReturnsCanceledTask()
        {
            // Arrange
            List <string>     log           = new List <string>();
            HttpActionContext actionContext = ContextUtil.CreateActionContext();

            // ExceptionFilters still have a chance to see the cancellation exception
            var exceptionFilter = CreateExceptionFilter((ec, ct) =>
            {
                log.Add("exceptionFilter");
                return(Task.Factory.StartNew(() => { }));
            });

            var filters = new IExceptionFilter[] { exceptionFilter };
            IExceptionLogger  exceptionLogger  = new Mock <IExceptionLogger>(MockBehavior.Strict).Object;
            IExceptionHandler exceptionHandler = new Mock <IExceptionHandler>(MockBehavior.Strict).Object;

            var actionResult = CreateStubActionResult(TaskHelpers.Canceled <HttpResponseMessage>());

            IHttpActionResult product = CreateProductUnderTest(actionContext, filters, exceptionLogger,
                                                               exceptionHandler, actionResult);

            // Act
            var result = product.ExecuteAsync(CancellationToken.None);

            // Assert
            Assert.NotNull(result);
            result.WaitUntilCompleted();
            Assert.Equal(TaskStatus.Canceled, result.Status);
            Assert.Equal(new string[] { "exceptionFilter" }, log.ToArray());
        }
예제 #4
0
 public void CancelSync(IAppBuilder app)
 {
     app.Run(context =>
     {
         return(TaskHelpers.Canceled());
     });
 }
        public override Task <object> ExecuteAsync(HttpControllerContext controllerContext, IDictionary <string, object> arguments, CancellationToken cancellationToken)
        {
            if (controllerContext == null)
            {
                throw Error.ArgumentNull("controllerContext");
            }

            if (arguments == null)
            {
                throw Error.ArgumentNull("arguments");
            }

            if (cancellationToken.IsCancellationRequested)
            {
                return(TaskHelpers.Canceled <object>());
            }

            try
            {
                object[] argumentValues = PrepareParameters(arguments, controllerContext);
                return(_actionExecutor.Value.Execute(controllerContext.Controller, argumentValues));
            }
            catch (Exception e)
            {
                return(TaskHelpers.FromError <object>(e));
            }
        }
예제 #6
0
        public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content,
                                                TransportContext transportContext, CancellationToken cancellationToken)
        {
            if (type == null)
            {
                throw Error.ArgumentNull("type");
            }
            if (writeStream == null)
            {
                throw Error.ArgumentNull("writeStream");
            }
            if (Request == null)
            {
                throw Error.InvalidOperation(SRResources.WriteToStreamAsyncMustHaveRequest);
            }
            if (cancellationToken.IsCancellationRequested)
            {
                return(TaskHelpers.Canceled());
            }

            HttpContentHeaders contentHeaders = content == null ? null : content.Headers;

            try
            {
                WriteToStream(type, value, writeStream, content, contentHeaders);
                return(TaskHelpers.Completed());
            }
            catch (Exception ex)
            {
                return(TaskHelpers.FromError(ex));
            }
        }
예제 #7
0
        public void TrySetFromTask_IfSourceTaskIsCanceled_CancelsTaskCompletionSource()
        {
            TaskCompletionSource <string> tcs = new TaskCompletionSource <string>();
            Task canceledTask = TaskHelpers.Canceled <object>();

            tcs.TrySetFromTask(canceledTask);

            Assert.Equal(TaskStatus.Canceled, tcs.Task.Status);
        }
예제 #8
0
        /// <summary>
        /// Returns a <see cref="Task"/> to deserialize an object of the given <paramref name="type"/> from the given <paramref name="readStream"/>
        /// </summary>
        /// <remarks>
        /// <para>This implementation throws a <see cref="NotSupportedException"/>. Derived types should override this method if the formatter
        /// supports reading.</para>
        /// <para>An implementation of this method should NOT close <paramref name="readStream"/> upon completion. The stream will be closed independently when
        /// the <see cref="HttpContent"/> instance is disposed.
        /// </para>
        /// </remarks>
        /// <param name="type">The type of the object to deserialize.</param>
        /// <param name="readStream">The <see cref="Stream"/> to read.</param>
        /// <param name="content">The <see cref="HttpContent"/> if available. It may be <c>null</c>.</param>
        /// <param name="formatterLogger">The <see cref="IFormatterLogger"/> to log events to.</param>
        /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
        /// <returns>A <see cref="Task"/> whose result will be an object of the given type.</returns>
        /// <exception cref="NotSupportedException">Derived types need to support reading.</exception>
        /// <seealso cref="CanReadType(Type)"/>
        public virtual Task <object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content,
                                                         IFormatterLogger formatterLogger, CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(TaskHelpers.Canceled <object>());
            }

            return(this.ReadFromStreamAsync(type, readStream, content, formatterLogger));
        }
예제 #9
0
        public override Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
        {
            VerifyBuffer(buffer, offset, count, allowEmpty: true);
            if (cancellationToken.IsCancellationRequested)
            {
                return(TaskHelpers.Canceled());
            }

            Write(buffer, offset, count);
            return(Task.FromResult <object>(null));
        }
예제 #10
0
        public override Task FlushAsync(CancellationToken cancellationToken)
        {
            if (cancellationToken.IsCancellationRequested)
            {
                return(TaskHelpers.Canceled());
            }

            Flush();

            // TODO: Wait for data to drain?

            return(Task.FromResult <object>(null));
        }
예제 #11
0
        public void ConvertFromCancelledTaskShouldBeHandled()
        {
            // Arrange
            TaskHelpers.Canceled()

            // Act
            .CastToObject()

            // Assert
            .ContinueWith(task =>
            {
                Assert.Equal(TaskStatus.Canceled, task.Status);
            });
        }
예제 #12
0
        private Task <TResult> ExecuteAsyncImpl(Task ignore)
        {
            if (this.cancellationToken.IsCancellationRequested)
            {
                if (this.previousTask != null)
                {
                    return(this.previousTask);
                }

                return(TaskHelpers.Canceled <TResult>());
            }

            Task <TResult> task;

            try
            {
                task = this.taskFunc();
            }
            catch (Exception ex)
            {
                if (!this.isTransient(ex))
                {
                    throw;
                }

                task = TaskHelpers.FromError <TResult>(ex);
            }

            if (task == null)
            {
                throw Error.Argument("taskFunc", Resources.TaskCannotBeNull);
            }

            if (task.Status == TaskStatus.RanToCompletion)
            {
                return(task);
            }

            if (task.Status == TaskStatus.Created)
            {
                throw Error.Argument("taskFunc", Resources.TaskMustBeScheduled);
            }

            return(task.ContinueWith <Task <TResult> >(this.ExecuteAsyncContinueWith, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default).Unwrap <TResult>());
        }
예제 #13
0
        private Task SendFileAsync(string name, long offset, long?count, CancellationToken cancel)
        {
            if (cancel.IsCancellationRequested)
            {
                return(TaskHelpers.Canceled());
            }

            try
            {
                OnStart();
                // TransmitFile is not safe to call on a background thread.  It should complete quickly so long as buffering is enabled.
                _httpContext.Response.TransmitFile(name, offset, count ?? -1);

                return(TaskHelpers.Completed());
            }
            catch (Exception ex)
            {
                return(TaskHelpers.FromError(ex));
            }
        }
예제 #14
0
        public void InvokeActionWithExceptionFilters_IfActionTaskIsCanceled_ReturnsCanceledTask()
        {
            // Arrange
            List <string> log                 = new List <string>();
            var           actionTask          = TaskHelpers.Canceled <HttpResponseMessage>();
            var           exceptionFilterMock = CreateExceptionFilterMock((ec, ct) =>
            {
                log.Add("exceptionFilter");
                return(Task.Factory.StartNew(() => { }));
            });
            var filters = new[] { exceptionFilterMock.Object };

            // Act
            var result = ApiController.InvokeActionWithExceptionFilters(actionTask, _actionContextInstance, CancellationToken.None, filters);

            // Assert
            Assert.NotNull(result);
            result.WaitUntilCompleted();
            Assert.Equal(TaskStatus.Canceled, result.Status);
            Assert.Equal(new string[] { }, log.ToArray());
        }
예제 #15
0
        public virtual Task ExecuteAsync(EventHandlerContext context, CancellationToken cancellationToken)
        {
            if (context == null)
            {
                throw Error.ArgumentNull("context");
            }

            if (cancellationToken.IsCancellationRequested)
            {
                return(TaskHelpers.Canceled());
            }

            try
            {
                return(this.actionExecutor.Value.Execute(context));
            }
            catch (Exception e)
            {
                return(TaskHelpers.FromError(e));
            }
        }
        public Task ExecuteActionFilterAsync_IfContinuationTaskWasCanceled_ReturnsCanceledTask()
        {
            // Arrange
            HttpActionContext            context    = ContextUtil.CreateActionContext();
            Mock <ActionFilterAttribute> filterMock = new Mock <ActionFilterAttribute>()
            {
                CallBase = true,
            };

            var filter = (IActionFilter)filterMock.Object;

            // Act & Assert
            return(Assert.ThrowsAsync <TaskCanceledException>(
                       () =>
                       filter.ExecuteActionFilterAsync(
                           context,
                           CancellationToken.None,
                           () => TaskHelpers.Canceled <HttpResponseMessage>()
                           )
                       ));
        }
예제 #17
0
        public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, HttpContent content,
                                                TransportContext transportContext, CancellationToken cancellationToken)
        {
            if (type == null)
            {
                throw Error.ArgumentNull("type");
            }
            if (writeStream == null)
            {
                throw Error.ArgumentNull("writeStream");
            }
            if (Request == null)
            {
                throw Error.InvalidOperation(SRResources.WriteToStreamAsyncMustHaveRequest);
            }
            if (cancellationToken.IsCancellationRequested)
            {
                return(TaskHelpers.Canceled());
            }

            try
            {
                HttpConfiguration configuration = Request.GetConfiguration();
                if (configuration == null)
                {
                    throw Error.InvalidOperation(SRResources.RequestMustContainConfiguration);
                }

                HttpContentHeaders contentHeaders = (content == null) ? null : content.Headers;
                UrlHelper          urlHelper      = Request.GetUrlHelper() ?? new UrlHelper(Request);

                Func <ODataSerializerContext> getODataSerializerContext = () =>
                {
                    return(new ODataSerializerContext()
                    {
                        Request = Request,
                        Url = urlHelper,
                    });
                };

                ODataSerializerProvider serializerProvider = Request.GetRequestContainer()
                                                             .GetRequiredService <ODataSerializerProvider>();

                ODataOutputFormatterHelper.WriteToStream(
                    type,
                    value,
                    Request.GetModel(),
                    ResultHelpers.GetODataResponseVersion(Request),
                    GetBaseAddressInternal(Request),
                    contentHeaders == null ? null : contentHeaders.ContentType,
                    new WebApiUrlHelper(urlHelper),
                    new WebApiRequestMessage(Request),
                    new WebApiRequestHeaders(Request.Headers),
                    (services) => ODataMessageWrapperHelper.Create(writeStream, contentHeaders, services),
                    (edmType) => serializerProvider.GetEdmTypeSerializer(edmType),
                    (objectType) => serializerProvider.GetODataPayloadSerializer(objectType, Request),
                    getODataSerializerContext);

                return(TaskHelpers.Completed());
            }
            catch (Exception ex)
            {
                return(TaskHelpers.FromError(ex));
            }
        }
예제 #18
0
        /// <summary>
        /// Performs asynchronous validation using a validation context and returns a collection of Validation Failures.
        /// </summary>
        /// <param name="context">Validation Context</param>
        /// <param name="cancellation"></param>
        /// <returns>A collection of validation failures</returns>
        public Task <IEnumerable <ValidationFailure> > ValidateAsync(ValidationContext context, CancellationToken cancellation)
        {
            try {
                var displayName = GetDisplayName(context.InstanceToValidate);

                if (PropertyName == null && displayName == null)
                {
                    //No name has been specified. Assume this is a model-level rule, so we should use empty string instead.
                    displayName = string.Empty;
                }

                // Construct the full name of the property, taking into account overriden property names and the chain (if we're in a nested validator)
                var propertyName = context.PropertyChain.BuildPropertyName(PropertyName ?? displayName);

                // Ensure that this rule is allowed to run.
                // The validatselector has the opportunity to veto this before any of the validators execute.
                if (!context.Selector.CanExecute(this, propertyName, context))
                {
                    return(TaskHelpers.FromResult(Enumerable.Empty <ValidationFailure>()));
                }

                var cascade  = cascadeModeThunk();
                var failures = new List <ValidationFailure>();

                var fastExit = false;

                // Firstly, invoke all syncronous validators and collect their results.
                foreach (var validator in validators.Where(v => !v.IsAsync))
                {
                    if (cancellation.IsCancellationRequested)
                    {
                        return(TaskHelpers.Canceled <IEnumerable <ValidationFailure> >());
                    }

                    var results = InvokePropertyValidator(context, validator, propertyName);

                    failures.AddRange(results);

                    // If there has been at least one failure, and our CascadeMode has been set to StopOnFirst
                    // then don't continue to the next rule
                    if (fastExit = (cascade == CascadeMode.StopOnFirstFailure && failures.Count > 0))
                    {
                        break;
                    }
                }

                //if StopOnFirstFailure triggered then we exit
                if (fastExit && failures.Count > 0)
                {
                    // Callback if there has been at least one property validator failed.
                    OnFailure(context.InstanceToValidate);

                    return(TaskHelpers.FromResult(failures.AsEnumerable()));
                }

                var asyncValidators = validators.Where(v => v.IsAsync).ToList();

                // if there's no async validators then we exit
                if (asyncValidators.Count == 0)
                {
                    if (failures.Count > 0)
                    {
                        // Callback if there has been at least one property validator failed.
                        OnFailure(context.InstanceToValidate);
                    }
                    else
                    {
                        return(RunDependentRulesAsync(failures, context, cancellation)
                               .Then(() => failures.AsEnumerable(), cancellationToken: cancellation));
                    }

                    return(TaskHelpers.FromResult(failures.AsEnumerable()));
                }

                //Then call asyncronous validators in non-blocking way
                var validations =
                    asyncValidators
//						.Select(v => v.ValidateAsync(new PropertyValidatorContext(context, this, propertyName), cancellation)
                    .Select(v => InvokePropertyValidatorAsync(context, v, propertyName, cancellation)
                            //this is thread safe because tasks are launched sequencially
                            .Then(fs => failures.AddRange(fs), runSynchronously: true)
                            );

                return
                    (TaskHelpers.Iterate(
                         validations,
                         breakCondition: _ => cascade == CascadeMode.StopOnFirstFailure && failures.Count > 0,
                         cancellationToken: cancellation
                         ).Then(async() => {
                    if (failures.Count > 0)
                    {
                        OnFailure(context.InstanceToValidate);
                    }
                    else
                    {
                        await RunDependentRulesAsync(failures, context, cancellation);
                    }

                    return failures.AsEnumerable();
                },
                                runSynchronously: true
                                ));
            }
            catch (Exception ex) {
                return(TaskHelpers.FromError <IEnumerable <ValidationFailure> >(ex));
            }
        }
예제 #19
0
        public void ExecuteActionFilterAsync_IfContinuationTaskWasCanceled_ReturnsCanceledTask()
        {
            // Arrange
            HttpActionContext            context    = ContextUtil.CreateActionContext();
            Mock <ActionFilterAttribute> filterMock = new Mock <ActionFilterAttribute>();
            var filter = (IActionFilter)filterMock.Object;

            // Act
            var result = filter.ExecuteActionFilterAsync(context, CancellationToken.None, () => TaskHelpers.Canceled <HttpResponseMessage>());

            // Assert
            result.WaitUntilCompleted();
            Assert.True(result.IsCanceled);
        }
 private static Task AbortResponseAsync()
 {
     // OWIN doesn't yet support an explicit Abort event. Returning a canceled task is the best contract at the
     // moment.
     return(TaskHelpers.Canceled());
 }
예제 #21
0
        public void ExecuteAsync_IsCancelled_And_Traces_When_Inner_IsCancelled()
        {
            // Arrange
            Mock <ApiController> mockController = new Mock <ApiController>()
            {
                CallBase = true
            };

            mockController.Setup(b => b.ExecuteAsync(It.IsAny <HttpControllerContext>(), It.IsAny <CancellationToken>())).Returns(TaskHelpers.Canceled <HttpResponseMessage>());

            HttpRequestMessage    request           = new HttpRequestMessage();
            HttpControllerContext controllerContext = ContextUtil.CreateControllerContext(request: request);

            controllerContext.ControllerDescriptor = _controllerDescriptor;
            controllerContext.Controller           = mockController.Object;

            HttpActionContext actionContext = ContextUtil.CreateActionContext(controllerContext, actionDescriptor: _mockActionDescriptor.Object);

            TestTraceWriter      traceWriter = new TestTraceWriter();
            HttpControllerTracer tracer      = new HttpControllerTracer(request, mockController.Object, traceWriter);

            TraceRecord[] expectedTraces = new TraceRecord[]
            {
                new TraceRecord(actionContext.Request, TraceCategories.ControllersCategory, TraceLevel.Info)
                {
                    Kind = TraceKind.Begin
                },
                new TraceRecord(actionContext.Request, TraceCategories.ControllersCategory, TraceLevel.Warn)
                {
                    Kind = TraceKind.End
                }
            };

            // Act
            Task      task   = ((IHttpController)tracer).ExecuteAsync(controllerContext, CancellationToken.None);
            Exception thrown = Assert.Throws <TaskCanceledException>(() => task.Wait());

            // Assert
            Assert.Equal <TraceRecord>(expectedTraces, traceWriter.Traces, new TraceRecordComparer());
        }
        public static Task TraceBeginEndAsync(this ITraceWriter traceWriter,
                                              HttpRequestMessage request,
                                              string category,
                                              TraceLevel level,
                                              string operatorName,
                                              string operationName,
                                              Action <TraceRecord> beginTrace,
                                              Func <Task> execute,
                                              Action <TraceRecord> endTrace,
                                              Action <TraceRecord> errorTrace)
        {
            if (traceWriter == null)
            {
                throw System.Web.Http.Error.ArgumentNull("traceWriter");
            }

            if (execute == null)
            {
                throw System.Web.Http.Error.ArgumentNull("execute");
            }

            bool isTracing = false;

            traceWriter.Trace(
                request,
                category,
                level,
                (TraceRecord traceRecord) =>
            {
                isTracing             = true;
                traceRecord.Kind      = TraceKind.Begin;
                traceRecord.Operator  = operatorName;
                traceRecord.Operation = operationName;
                if (beginTrace != null)
                {
                    beginTrace(traceRecord);
                }
            });
            try
            {
                Task task = execute();

                // If we are not tracing, there is no need to ContinueWith
                if (!isTracing || task == null)
                {
                    return(task);
                }

                Task <Task> returnTask = task.ContinueWith <Task>((t) =>
                {
                    if (t.IsCanceled)
                    {
                        traceWriter.Trace(
                            request,
                            category,
                            TraceLevel.Warn,
                            (TraceRecord traceRecord) =>
                        {
                            traceRecord.Kind      = TraceKind.End;
                            traceRecord.Operator  = operatorName;
                            traceRecord.Operation = operationName;
                            traceRecord.Message   = SRResources.TraceCancelledMessage;
                            if (errorTrace != null)
                            {
                                errorTrace(traceRecord);
                            }
                        });

                        return(TaskHelpers.Canceled());
                    }

                    if (t.IsFaulted)
                    {
                        traceWriter.Trace(
                            request,
                            category,
                            TraceLevel.Error,
                            (TraceRecord traceRecord) =>
                        {
                            traceRecord.Kind      = TraceKind.End;
                            traceRecord.Exception = t.Exception.GetBaseException();
                            traceRecord.Operator  = operatorName;
                            traceRecord.Operation = operationName;
                            if (errorTrace != null)
                            {
                                errorTrace(traceRecord);
                            }
                        });

                        return(TaskHelpers.FromErrors(t.Exception.InnerExceptions));
                    }

                    traceWriter.Trace(
                        request,
                        category,
                        level,
                        (TraceRecord traceRecord) =>
                    {
                        traceRecord.Kind      = TraceKind.End;
                        traceRecord.Operator  = operatorName;
                        traceRecord.Operation = operationName;
                        if (endTrace != null)
                        {
                            endTrace(traceRecord);
                        }
                    });

                    return(TaskHelpers.Completed());
                });

                return(returnTask.FastUnwrap());
            }
            catch (Exception ex)
            {
                if (isTracing)
                {
                    traceWriter.Trace(
                        request,
                        category,
                        TraceLevel.Error,
                        (TraceRecord traceRecord) =>
                    {
                        traceRecord.Kind      = TraceKind.End;
                        traceRecord.Operator  = operatorName;
                        traceRecord.Operation = operationName;
                        traceRecord.Exception = ex;
                        if (errorTrace != null)
                        {
                            errorTrace(traceRecord);
                        }
                    });
                }
                throw;
            }
        }