public void ProgressObserver_ProgressUpdate_VisibleHiddenNotImpacting()
        {
            // Setup 
            bool randomIndeterminate = Environment.TickCount % 2 == 0;
            ConfigurableProgressTestOperation noImpacting1 = CreateRandomStep(visible: true, indeterminate: randomIndeterminate, impacting: false);
            noImpacting1.ExecutionState = StepExecutionState.NotStarted;
            noImpacting1.Progress = 0;

            ConfigurableProgressTestOperation hidden1 = CreateRandomStep(visible: false, indeterminate: false, impacting: true);
            hidden1.ExecutionState = StepExecutionState.NotStarted;
            hidden1.Progress = 0;

            ConfigurableProgressTestOperation noImpacting2 = CreateRandomStep(visible: true, indeterminate: randomIndeterminate, impacting: false);
            noImpacting2.ExecutionState = StepExecutionState.NotStarted;
            noImpacting2.Progress = 0;

            ConfigurableProgressTestOperation visible1 = CreateRandomStep(visible: true, indeterminate: false, impacting: true);
            visible1.ExecutionState = StepExecutionState.NotStarted;
            visible1.Progress = 0;

            ConfigurableProgressTestOperation visible2 = CreateRandomStep(visible: true, indeterminate: false, impacting: true);
            visible2.ExecutionState = StepExecutionState.NotStarted;
            visible2.Progress = 0;

            ConfigurableProgressTestOperation hidden2 = CreateRandomStep(visible: false, indeterminate: false, impacting: true);
            hidden2.ExecutionState = StepExecutionState.NotStarted;
            hidden2.Progress = 0;

            ConfigurableProgressTestOperation[] steps = new[] { noImpacting1, hidden1, noImpacting2, visible1, visible2, hidden2 };
            this.progressEvents.Steps = steps;
            this.CreateTestSubject();
            double mainProgressSections = steps.Count(s => s.ImpactsProgress);

            // Verify initial state
            VerifyProgress(this.testVisualizer, 0, null, 0);

            ExecutionVerifier verifier = new ExecutionVerifier(this.testVisualizer, this.testSubject);
            verifier.AppendStepToGroup(0, hidden1);
            verifier.AppendStepToGroup(0, visible1);
            verifier.AppendStepToGroup(1, visible2);
            verifier.AppendStepToGroup(1, hidden2);

            // Non-impacting started to execute
            noImpacting1.Progress = 0;
            noImpacting1.ExecutionState = StepExecutionState.Executing;
            verifier.RunAndVerifyExecutingStep(this.progressEvents, noImpacting1, null);

            // Non-impacting reports progress
            noImpacting1.Progress = 0.5;
            verifier.RunAndVerifyExecutingStep(this.progressEvents, noImpacting1, null);

            // Non-impacting completes
            noImpacting1.Progress = 1.0;
            noImpacting1.ExecutionState = StepExecutionState.Succeeded;
            verifier.RunAndVerifyExecutingStep(this.progressEvents, noImpacting1, null);

            // Hidden1 starts
            hidden1.ExecutionState = StepExecutionState.Executing;
            verifier.RunAndVerifyExecutingStep(this.progressEvents, hidden1, 0);

            // Hidden1 reports progress
            hidden1.Progress = 0.5;
            verifier.ExpectedSubProgress = hidden1.Progress / 2.0; // relative to the number of sub steps in group
            verifier.ExpectedMainProgress = hidden1.Progress / mainProgressSections; // relative to the number of impacting steps
            verifier.RunAndVerifyExecutingStep(this.progressEvents, hidden1, 0);

            // Hidden1 completes
            hidden1.ExecutionState = StepExecutionState.Cancelled;
            verifier.ExpectedSubProgress = 1.0 / 2.0; // relative to the number of sub steps in group
            verifier.ExpectedMainProgress = 1.0 / mainProgressSections; // relative to the number of impacting steps
            verifier.RunAndVerifyExecutingStep(this.progressEvents, hidden1, 0);

            // Non-impacting started to execute
            noImpacting2.Progress = 0;
            noImpacting2.ExecutionState = StepExecutionState.Executing;
            verifier.RunAndVerifyExecutingStep(this.progressEvents, noImpacting2, 0);

            // Non-impacting reports progress
            noImpacting2.Progress = 0.5;
            verifier.RunAndVerifyExecutingStep(this.progressEvents, noImpacting2, 0);

            // Non-impacting completes
            noImpacting2.Progress = 1.0;
            noImpacting2.ExecutionState = StepExecutionState.Succeeded;
            verifier.RunAndVerifyExecutingStep(this.progressEvents, noImpacting2, 0);

            // Visible1 starts
            visible1.ExecutionState = StepExecutionState.Executing;
            verifier.RunAndVerifyExecutingStep(this.progressEvents, visible1, 0);

            // Visible1 reports progress
            visible1.Progress = 1.0;
            verifier.ExpectedSubProgress = 2.0 / 2.0; // relative to the number of sub steps in group
            verifier.ExpectedMainProgress = 2.0 / mainProgressSections; // relative to the number of impacting steps
            verifier.RunAndVerifyExecutingStep(this.progressEvents, visible1, 0);

            // Visible1 completes
            visible1.ExecutionState = StepExecutionState.Failed;
            verifier.ExpectedSubProgress = 1.0;
            verifier.ExpectedMainProgress = 2.0 / mainProgressSections; // relative to the number of impacting steps
            verifier.RunAndVerifyExecutingStep(this.progressEvents, visible1, 0);

            // Visible2 completes
            visible2.ExecutionState = StepExecutionState.Succeeded;
            verifier.ExpectedSubProgress = 1.0 / 2.0;  // relative to the number of sub steps in group
            verifier.ExpectedMainProgress = 3.0 / mainProgressSections;
            verifier.RunAndVerifyExecutingStep(this.progressEvents, visible2, 1);

            // Hidden2 completes
            hidden2.ExecutionState = StepExecutionState.Succeeded;
            verifier.ExpectedSubProgress = 2.0 / 2.0; // relative to the number of sub steps in group
            verifier.ExpectedMainProgress = 4.0 / mainProgressSections;
            verifier.RunAndVerifyExecutingStep(this.progressEvents, hidden2, 1);
        }
        public void SequentialProgressController_ExecutionOrder()
        {
            // Setup
            IProgressStep[] stepOperations = null;
            int expectedOperation = 0;
            Action<CancellationToken, IProgressStepExecutionEvents> operation = (c, e) =>
                {
                    Assert.AreSame(stepOperations[expectedOperation], (IProgressStep)e, "Unexpected execution order");
                    expectedOperation++;
                };

            ProgressStepDefinition[] definitions = new[]
            {
                new ProgressStepDefinition(null, StepAttributes.Default, operation),
                new ProgressStepDefinition(null, StepAttributes.Hidden, operation),
                new ProgressStepDefinition(null, StepAttributes.BackgroundThread, operation),
                new ProgressStepDefinition(null, StepAttributes.Indeterminate, operation),
                new ProgressStepDefinition(null, StepAttributes.NonCancellable, operation)
            };

            ProgressEventsVerifier verifier = this.InitializeTestSubjectWithTestErrorHandling(definitions);
            stepOperations = this.testSubject.Steps.ToArray();

            // Execute
            this.testSubject.Start().Wait();

            // Verify
            Assert.AreEqual(expectedOperation, definitions.Length, "Executed unexpected number of times");
        }