Exemple #1
0
        async Task <StepExecutionState> IProgressStepOperation.Run(CancellationToken cancellationToken, IProgressStepExecutionEvents progressCallback)
        {
            if (this.ExecutionState != StepExecutionState.NotStarted)
            {
                throw new InvalidOperationException(ProgressResources.StepOperationWasAlreadyExecuted);
            }

            if (this.Cancellable && cancellationToken.IsCancellationRequested)
            {
                return(this.ExecutionState = StepExecutionState.Cancelled);
            }

            VsTaskRunContext context = GetContext(this.Execution);

            StepExecutionState stepState = await VsThreadingHelper.RunTask <StepExecutionState>(this.controller, context,
                                                                                                () =>
            {
                DoStatefulExecution(progressCallback, cancellationToken);
                return(this.ExecutionState);
            },

                                                                                                cancellationToken);

            return(stepState);
        }
Exemple #2
0
 private void ControllerStarted(object sender, ProgressEventArgs e)
 {
     // Show can be modal and block, so begin invoke it
     VsThreadingHelper.BeginTask(this.serviceProvider, VsTaskRunContext.UIThreadNormalPriority,
                                 this.host.Show);
     // Flag that handled to assist with the verification, otherwise the controller will assert
     e.Handled();
 }
Exemple #3
0
 private void OnCancellationSupportChanged(object sender, CancellationSupportChangedEventArgs e)
 {
     VsThreadingHelper.RunInline(this.serviceProvider, VsTaskRunContext.UIThreadNormalPriority, () =>
     {
         ChangeCancellability(e.Cancellable);
     });
     // Flag that handled to assist with the verification, otherwise the controller will assert
     e.Handled();
 }
Exemple #4
0
 private static ProgressObserver CreateAndConfigureInstance(IServiceProvider serviceProvider, IProgressVisualizer visualizer, IProgressEvents progressEvents, ICommand cancelCommand, ProgressControllerViewModel state)
 {
     return(VsThreadingHelper.RunInline(serviceProvider, VsTaskRunContext.UIThreadNormalPriority, () =>
     {
         ProgressObserver returnValue = new ProgressObserver(serviceProvider, visualizer, progressEvents, state);
         returnValue.CancelCommand = cancelCommand;
         return returnValue;
     }, null));
 }
Exemple #5
0
        /// <summary>
        /// Stops the specified <see cref="ProgressObserver"/> from observing.
        /// The method is thread safe.
        /// </summary>
        /// <param name="observer">An existing <see cref="ProgressObserver"/> to stop observing with</param>
        public static void StopObserving(ProgressObserver observer)
        {
            if (observer == null)
            {
                throw new ArgumentNullException(nameof(observer));
            }

            if (observer.disposed)
            {
                return;
            }

            VsThreadingHelper.RunInline(observer.serviceProvider, VsTaskRunContext.UIThreadNormalPriority, () => ((IDisposable)observer).Dispose());
        }
        /// <summary>
        /// The <see cref="ProgressControllerStep"/> which are used by default will swallow the assert exceptions
        /// which means that investigating why something is failing requires more time and effort.
        /// This extension method will record the first <see cref="UnitTestAssertException"/> which was thrown during
        /// execution and will rethrow it on a way that will allow the test to fail and see the original stack
        /// that caused the test failure (on Finished event)
        /// </summary>
        /// <param name="controller">The controller to configure</param>
        /// <returns>The notifier that was used for configuration of the assert exception</returns>
        public static ConfigurableErrorNotifier ConfigureToThrowAssertExceptions(SequentialProgressController controller)
        {
            Assert.IsNotNull(controller, "Controller argument is required");
            Assert.IsNotNull(controller.Steps, "Controller needs to be initialized");

            ConfigurableErrorNotifier errorHandler = new ConfigurableErrorNotifier();

            controller.ErrorNotificationManager.AddNotifier(errorHandler);

            UnitTestAssertException originalException = null;

            // Controller.Finished is executed out of the awaitable state machine and on the calling (UI) thread
            // which means that at this point the test runtime engine will be able to catch it and fail the test
            EventHandler <ProgressControllerFinishedEventArgs> onFinished = null;

            onFinished = (s, e) =>
            {
                // Need to register on the UI thread
                VsThreadingHelper.RunTask(controller, Microsoft.VisualStudio.Shell.VsTaskRunContext.UIThreadNormalPriority, () =>
                {
                    controller.Finished -= onFinished;
                }).Wait();

                // Satisfy the sequential controller verification code
                e.Handled();

                if (originalException != null)
                {
                    Assert.AreEqual(ProgressControllerResult.Failed, e.Result, "Expected to be failed since the assert failed which causes an exception");
                    throw new RestoredUnitTestAssertException(originalException.Message, originalException);
                }
            };

            // Need to register on the UI thread
            VsThreadingHelper.RunTask(controller, Microsoft.VisualStudio.Shell.VsTaskRunContext.UIThreadNormalPriority, () =>
            {
                controller.Finished += onFinished;
            }).Wait();

            errorHandler.NotifyAction = (e) =>
            {
                // Only the first one
                if (originalException == null)
                {
                    originalException = e as UnitTestAssertException;
                }
            };
            return(errorHandler);
        }
 /// <summary>
 /// Invokes the <see cref="StateChanged"/> event based on the <see cref="ExecutionState"/> of the object
 /// </summary>
 protected virtual void OnExecutionStateChanged()
 {
     if (this.StateChangedPrivate != null)
     {
         VsThreadingHelper.RunInline(this.controller, VsTaskRunContext.UIThreadBackgroundPriority,
                                     () =>
         {
             var delegates = this.StateChangedPrivate;
             if (delegates != null)
             {
                 delegates(this, new StepExecutionChangedEventArgs(this));
             }
         });
     }
 }
        void IProgressErrorNotifier.Notify(Exception ex)
        {
            if (ex == null)
            {
                throw new ArgumentNullException(nameof(ex));
            }

            VsThreadingHelper.RunInline(this.serviceProvider, VsTaskRunContext.UIThreadNormalPriority, () =>
            {
                int hr = this.pane.OutputStringThreadSafe(ProgressControllerHelper.FormatErrorMessage(ex, this.messageFormat, this.logFullException) + Environment.NewLine);

                if (this.ensureOutputVisible && ErrorHandler.Succeeded(hr) && ErrorHandler.Succeeded(pane.Activate()))
                {
                    ShowOutputWindowFrame(serviceProvider);
                }
            });
        }
Exemple #9
0
        private void ControllerFinished(object sender, ProgressControllerFinishedEventArgs e)
        {
            this.IsFinished = true;

            VsThreadingHelper.RunInline(this.serviceProvider, VsTaskRunContext.BackgroundThread, () =>
            {
                // Give the last progress a chance to render
                System.Threading.Thread.Sleep(DelayAfterFinishInMS);
            });
            VsThreadingHelper.RunInline(this.serviceProvider, VsTaskRunContext.UIThreadNormalPriority, () =>
            {
                this.host.Hide();
                ((IDisposable)this).Dispose();
            });
            // Flag that handled to assist with the verification, otherwise the controller will assert
            e.Handled();
        }
Exemple #10
0
 private void OnStepStateChanged(object sender, StepExecutionChangedEventArgs args)
 {
     if (this.StepExecutionChangedPrivate != null)
     {
         VsThreadingHelper.RunInline(this, VsTaskRunContext.UIThreadNormalPriority,
                                     () =>
         {
             var delegates = this.StepExecutionChangedPrivate;
             if (delegates != null)
             {
                 delegates(sender, args);
                 // Verify that the observer handled it since now easy way of testing
                 // serialized raising and handling of the event across the classes
                 args.CheckHandled();
             }
         });
     }
 }
Exemple #11
0
 private void OnCancellableChanged(bool cancellable)
 {
     if (this.CancellationSupportChangedPrivate != null)
     {
         VsThreadingHelper.RunInline(this, VsTaskRunContext.UIThreadNormalPriority,
                                     () =>
         {
             var delegates = this.CancellationSupportChangedPrivate;
             if (delegates != null)
             {
                 CancellationSupportChangedEventArgs args = new CancellationSupportChangedEventArgs(cancellable);
                 delegates(this, args);
                 // Verify that the observer handled it since now easy way of testing
                 // serialized raising and handling of the event across the classes
                 args.CheckHandled();
             }
         });
     }
 }
Exemple #12
0
        void IProgressErrorNotifier.Notify(Exception ex)
        {
            if (ex == null)
            {
                throw new ArgumentNullException(nameof(ex));
            }

            VsThreadingHelper.RunInline(this.serviceProvider, VsTaskRunContext.UIThreadNormalPriority, () =>
            {
                IVsActivityLog log = (IVsActivityLog)this.serviceProvider.GetService(typeof(SVsActivityLog));
                if (log != null)
                {
                    log.LogEntry((uint)__ACTIVITYLOG_ENTRYTYPE.ALE_ERROR, this.entrySource, ProgressControllerHelper.FormatErrorMessage(ex, messageFormat, logWholeMessage));
                }
                else
                {
                    Debug.Fail("Cannot find SVsActivityLog");
                }
            });
        }
Exemple #13
0
        private void OnFinished(ProgressControllerResult result)
        {
            this.IsFinished = true;
            this.ThreadSafeDisposeCancellationTokenSource();

            VsThreadingHelper.RunInline(this, VsTaskRunContext.UIThreadNormalPriority, () =>
            {
                ConfigureStepEventListeners(false);

                var delegates = this.FinishedPrivate;
                if (delegates != null)
                {
                    ProgressControllerFinishedEventArgs args = new ProgressControllerFinishedEventArgs(result);
                    delegates(this, args);
                    // Verify that the observer handled it since now easy way of testing
                    // serialized raising and handling of the event across the classes
                    args.CheckHandled();
                }
            });
        }
Exemple #14
0
        private void OnStepExecutionChanged(object sender, StepExecutionChangedEventArgs e)
        {
            try
            {
                // Don't have to do it on the UI thread since we don't expect the mapping to change during execution
                if (!this.progressStepToViewModelMapping.ContainsKey(e.Step))
                {
                    Debug.Assert(!e.Step.ImpactsProgress, "View model out of sync. The step execution is for unexpected step");
                    return;
                }

                VsThreadingHelper.RunInline(this.serviceProvider, VsTaskRunContext.UIThreadNormalPriority, () =>
                {
                    this.UpdateViewModelStep(e);

                    this.UpdateMainProgress(e);
                });
            }
            finally
            {
                // Flag that handled to assist with the verification, otherwise the controller will assert
                e.Handled();
            }
        }
Exemple #15
0
        /// <summary>
        /// Starts executing the initialized steps.
        /// The method is not thread safe but can be called from any thread.
        /// </summary>
        /// <returns>An await-able</returns>
        public async TPL.Task <ProgressControllerResult> Start()
        {
            if (this.IsStarted)
            {
                throw new InvalidOperationException(ProgressResources.AlreadyStartedException);
            }

            this.OnStarted();

            ProgressControllerResult controllerResult = await VsThreadingHelper.RunTask <ProgressControllerResult>(this, VsTaskRunContext.BackgroundThread,
                                                                                                                   () =>
            {
                ThreadHelper.ThrowIfOnUIThread();

                // By default can abort, the individual step may changed that
                this.CanAbort = true;

                ProgressControllerResult result = ProgressControllerResult.Cancelled;
                foreach (IProgressStepOperation operation in this.progressStepOperations)
                {
                    // Try to cancel (in case the step itself will not cancel itself)
                    if (this.cancellationTokenSource.IsCancellationRequested)
                    {
                        result = ProgressControllerResult.Cancelled;
                        break;
                    }

                    this.CanAbort = operation.Step.Cancellable;

                    IProgressStepExecutionEvents notifier = this.stepFactory.GetExecutionCallback(operation);

                    // Give another try before running the operation (there's a test that covers cancellation
                    // before running the operation which requires this check after CanAbort is set)
                    if (this.cancellationTokenSource.IsCancellationRequested)
                    {
                        result = ProgressControllerResult.Cancelled;
                        break;
                    }

                    StepExecutionState stepResult = operation.Run(this.cancellationTokenSource.Token, notifier).Result;

                    /* Not trying to cancel here intentionally. The reason being
                     * in case the step was the last one, there's nothing to cancel really,
                     * otherwise there will be an attempt to cancel just before the next
                     * step execution*/

                    if (stepResult == StepExecutionState.Succeeded)
                    {
                        result = ProgressControllerResult.Succeeded;
                    }
                    else if (stepResult == StepExecutionState.Failed)
                    {
                        result = ProgressControllerResult.Failed;
                        break;
                    }
                    else if (stepResult == StepExecutionState.Cancelled)
                    {
                        result = ProgressControllerResult.Cancelled;
                        break;
                    }
                    else
                    {
                        Debug.Fail("Unexpected step execution result:" + stepResult);
                    }
                }

                return(result);
            },

                                                                                                                   this.cancellationTokenSource.Token);

            this.OnFinished(controllerResult);

            return(controllerResult);
        }