/// <summary> /// Signals that an action is beginning. /// </summary> /// <param name="planRun">The planrun for the currently executing testplan.</param> /// <param name="item">The item affected by the current action. This can be either a testplan or a teststep.</param> /// <param name="stage">The stage that is beginning.</param> /// <param name="cancellationToken">Used to cancel the step early.</param> public void BeginStep(TestPlanRun planRun, ITestStepParent item, TestPlanExecutionStage stage, CancellationToken cancellationToken) { switch (stage) { case TestPlanExecutionStage.Execute: if (item is TestPlan testPlan) { var resources = ResourceManagerUtils.GetResourceNodes(StaticResources.Cast <object>().Concat(EnabledSteps)); // Proceed to open resources in case they have been changed or closed since last opening/executing the testplan. // In case any are null, we need to do this before the resource prompt to allow a ILockManager implementation to // set the resource first. if (resources.Any(r => r.Resource == null)) { beginOpenResoureces(resources, cancellationToken); } testPlan.StartResourcePromptAsync(planRun, resources.Select(res => res.Resource)); if (resources.Any(r => openTasks.ContainsKey(r.Resource) == false)) { beginOpenResoureces(resources, cancellationToken); } } break; case TestPlanExecutionStage.Open: if (item is TestPlan) { var resources = ResourceManagerUtils.GetResourceNodes(StaticResources.Cast <object>().Concat(EnabledSteps)); beginOpenResoureces(resources, cancellationToken); } break; case TestPlanExecutionStage.Run: case TestPlanExecutionStage.PrePlanRun: { bool openCompletedWithSuccess = openTasks.Values.All(x => x.Status == TaskStatus.RanToCompletion); if (!openCompletedWithSuccess) { // open did not complete or threw an exception. using (TimeoutOperation.Create(() => TestPlan.PrintWaitingMessage(Resources))) WaitUntilAllResourcesOpened(cancellationToken); } break; } case TestPlanExecutionStage.PostPlanRun: break; } }
/// <summary> /// Signals that an action is beginning. /// </summary> /// <param name="planRun">The planrun for the currently executing testplan.</param> /// <param name="item">The item affected by the current action. This can be either a testplan or a teststep.</param> /// <param name="stage">The stage that is beginning.</param> /// <param name="cancellationToken">Used to cancel the step early.</param> public void BeginStep(TestPlanRun planRun, ITestStepParent item, TestPlanExecutionStage stage, CancellationToken cancellationToken) { switch (stage) { case TestPlanExecutionStage.Open: case TestPlanExecutionStage.Execute: { var resources = ResourceManagerUtils.GetResourceNodes(StaticResources); if (item is TestPlan plan && stage == TestPlanExecutionStage.Execute) { // Prompt for metadata for all resources, not only static ones. var testPlanResources = ResourceManagerUtils.GetResourceNodes(EnabledSteps); plan.StartResourcePromptAsync(planRun, resources.Concat(testPlanResources).Select(res => res.Resource)); } if (resources.All(r => r.Resource?.IsConnected ?? false)) { return; } // Call ILockManagers before checking for null try { lockManager.BeforeOpen(resources, cancellationToken); } finally { lock (resourceWithBeforeOpenCalled) { resourceWithBeforeOpenCalled.AddRange(resources); } } try { // Check null resources if (resources.Any(res => res.Resource == null)) { // Now check resources since we know one of them should have a null resource resources.ForEach(res => { if (res.StrongDependencies.Contains(null) || res.WeakDependencies.Contains(null)) { throw new Exception(String.Format("Resource property not set on resource {0}. Please configure resource.", res.Resource)); } }); } } finally { OpenResources(resources, cancellationToken); } break; } case TestPlanExecutionStage.Run: if (item is ITestStep step) { var resources = ResourceManagerUtils.GetResourceNodes(new List <object> { step }); if (resources.Any()) { // Call ILockManagers before checking for null try { lockManager.BeforeOpen(resources, cancellationToken); } finally { lock (resourceWithBeforeOpenCalled) { resourceWithBeforeOpenCalled.AddRange(resources); } } try { // Check null resources if (resources.Any(res => res.Resource == null)) { step.CheckResources(); // Now check resources since we know one of them should have a null resource resources.ForEach(res => { if (res.StrongDependencies.Contains(null) || res.WeakDependencies.Contains(null)) { throw new Exception(String.Format("Resource property not set on resource {0}. Please configure resource.", res.Resource)); } }); } } finally { lock (resourceLock) { resourceDependencies[step] = resources.Select(x => x.Resource).ToList(); foreach (ResourceNode n in resources) { if (n.Resource is IResource resource) { if (!resourceReferenceCount.ContainsKey(resource)) { resourceReferenceCount[resource] = 0; } resourceReferenceCount[resource] += 1; } } } OpenResources(resources, cancellationToken); } WaitHandle.WaitAny(new[] { planRun.PromptWaitHandle, planRun.MainThread.AbortToken.WaitHandle }); } } break; } }