private void PackageStatusInfo() { LocalEventQueue <SequenceStatusInfo> statusQueue = _context.StatusQueue; while (!_cancellation.IsCancellationRequested) { // 标记事件处理flag为阻塞中 Thread.MemoryBarrier(); Thread.VolatileWrite(ref _eventProcessFlag, 0); SequenceStatusInfo statusInfo = statusQueue.WaitUntilMessageCome(); // 如果为null,StatusQueue已经停止接收,直接跳出 if (null == statusInfo) { return; } // 标记事件处理flag为处理中 Thread.MemoryBarrier(); Thread.VolatileWrite(ref _eventProcessFlag, 1); SendSequenceStatusMessage(statusInfo); // 标记事件处理flag为处理结束 Thread.MemoryBarrier(); Thread.VolatileWrite(ref _eventProcessFlag, 2); } // 标记事件处理flag为结束状态 Thread.MemoryBarrier(); Thread.VolatileWrite(ref _eventProcessFlag, 3); }
protected override void FlowTaskAction() { SendStartMessage(); // 打印状态日志 Context.LogSession.Print(LogLevel.Info, Context.SessionId, $"Start run sequence {_sequenceIndex}."); Context.State = RuntimeState.Running; SessionTaskEntity sessionTaskEntity = Context.SessionTaskEntity; try { sessionTaskEntity.InvokeSetUp(); RuntimeState setUpState = sessionTaskEntity.GetSequenceTaskState(CommonConst.SetupIndex); // 如果SetUp执行失败,则执行TearDown,且配置所有序列为失败状态,并发送所有序列都失败的信息 if (CoreUtils.IsFailed(setUpState)) { // 打印状态日志 Context.LogSession.Print(LogLevel.Error, Context.SessionId, "Run setup failed."); for (int i = 0; i < sessionTaskEntity.SequenceCount; i++) { SequenceTaskEntity sequenceTaskEntity = sessionTaskEntity.GetSequenceTaskEntity(i); sequenceTaskEntity.State = RuntimeState.Failed; FailedInfo failedInfo = new FailedInfo(Context.I18N.GetStr("SetUpFailed"), FailedType.SetUpFailed); CallStack sequenceStack = ModuleUtils.GetSequenceStack(i, sequenceTaskEntity.RootCoroutineId); SequenceStatusInfo statusInfo = new SequenceStatusInfo(i, sequenceStack, StatusReportType.Failed, setUpState, StepResult.NotAvailable, failedInfo) { ExecutionTime = DateTime.Now, ExecutionTicks = -1, CoroutineId = sequenceTaskEntity.RootCoroutineId }; Context.StatusQueue.Enqueue(statusInfo); } } else { sessionTaskEntity.InvokeSequence(_sequenceIndex); } } finally { sessionTaskEntity.InvokeTearDown(); Context.State = RuntimeState.Over; this.Next = null; SendOverMessage(); // 打印状态日志 Context.LogSession.Print(LogLevel.Info, Context.SessionId, "Run single sequence over."); } }
protected void RecordRuntimeStatus() { SequenceStatusInfo statusInfo = new SequenceStatusInfo(SequenceIndex, this.GetStack(), StatusReportType.Record, RuntimeState.Running, Result) { ExecutionTime = Actuator.ExecutionTime, ExecutionTicks = Actuator.ExecutionTicks, CoroutineId = this.Coroutine.Id }; // 更新watch变量值 statusInfo.WatchDatas = Context.VariableMapper.GetKeyVariablesValues(StepData); Context.StatusQueue.Enqueue(statusInfo); }
private void RecordInvocationError(Exception ex, FailedType failedType) { FailedInfo failedInfo = new FailedInfo(ex, failedType); SequenceStatusInfo statusInfo = new SequenceStatusInfo(SequenceIndex, this.GetStack(), StatusReportType.Record, RuntimeState.Running, Result, failedInfo) { ExecutionTime = Actuator.ExecutionTime, ExecutionTicks = Actuator.ExecutionTicks, CoroutineId = this.Coroutine.Id, WatchDatas = Context.VariableMapper.GetKeyVariablesValues(StepData) }; // 一旦失败,需要记录WatchData Context.StatusQueue.Enqueue(statusInfo); Context.LogSession.Print(LogLevel.Error, Context.SessionId, ex.Message); }
public void SetStatusAndSendErrorEvent(StepResult result, FailedInfo failedInfo) { this.Result = result; // 如果发生错误,无论该步骤是否被配置为recordStatus,都需要发送状态信息 SequenceStatusInfo statusInfo = new SequenceStatusInfo(SequenceIndex, this.GetStack(), StatusReportType.Record, RuntimeState.Running, Result, failedInfo) { ExecutionTime = Actuator.ExecutionTime, CoroutineId = Coroutine.Id, ExecutionTicks = Actuator.ExecutionTicks }; // 更新watch变量值 statusInfo.WatchDatas = Context.VariableMapper.GetKeyVariablesValues(StepData); Context.StatusQueue.Enqueue(statusInfo); }
private void SendSetupFailedEvents(SessionTaskEntity sessionTaskEntity, RuntimeState sequenceState) { for (int i = 0; i < sessionTaskEntity.SequenceCount; i++) { SequenceTaskEntity sequenceTaskEntity = sessionTaskEntity.GetSequenceTaskEntity(i); sequenceTaskEntity.State = RuntimeState.Failed; FailedInfo failedInfo = new FailedInfo(Context.I18N.GetStr("SetUpFailed"), FailedType.SetUpFailed); CallStack sequenceStack = ModuleUtils.GetSequenceStack(i, sequenceTaskEntity.RootCoroutineId); SequenceStatusInfo statusInfo = new SequenceStatusInfo(i, sequenceStack, StatusReportType.Failed, sequenceState, StepResult.NotAvailable, failedInfo) { ExecutionTime = DateTime.Now, ExecutionTicks = -1, CoroutineId = sequenceTaskEntity.RootCoroutineId }; Context.StatusQueue.Enqueue(statusInfo); } }
protected override void FlowTaskAction() { SendStartMessage(); // 打印状态日志 Context.LogSession.Print(LogLevel.Info, Context.SessionId, "Start test project setup."); Context.State = RuntimeState.Running; SessionTaskEntity sessionTaskEntity = Context.SessionTaskEntity; sessionTaskEntity.InvokeSetUp(); RuntimeState setUpState = sessionTaskEntity.GetSequenceTaskState(CommonConst.SetupIndex); // 如果SetUp执行失败,则执行TearDown,且配置所有序列为失败状态,并发送所有序列都失败的信息 if (CoreUtils.IsFailed(setUpState)) { // 打印状态日志 Context.LogSession.Print(LogLevel.Error, Context.SessionId, "Run testproject setup failed."); for (int i = 0; i < sessionTaskEntity.SequenceCount; i++) { sessionTaskEntity.GetSequenceTaskEntity(i).State = RuntimeState.Failed; FailedInfo failedInfo = new FailedInfo(Context.I18N.GetStr("SetUpFailed"), FailedType.SetUpFailed); SequenceStatusInfo statusInfo = new SequenceStatusInfo(i, ModuleUtils.GetSequenceStack(i, 0), StatusReportType.Failed, setUpState, StepResult.NotAvailable, failedInfo) { ExecutionTime = DateTime.Now, ExecutionTicks = -1, CoroutineId = 0 }; Context.StatusQueue.Enqueue(statusInfo); } sessionTaskEntity.InvokeTearDown(); // 打印状态日志 Context.LogSession.Print(LogLevel.Info, Context.SessionId, "Teardown execution over."); return; } // 打印状态日志 Context.LogSession.Print(LogLevel.Info, Context.SessionId, "Testproject setup execution over."); this._wakeTimer = new Timer(WakeThreadWhenCtrlMessageCome, null, Constants.WakeTimerInterval, Constants.WakeTimerInterval); _blockEvent.WaitOne(); if (null == Context.CtrlStartMessage) { Context.LogSession.Print(LogLevel.Error, Context.SessionId, "Receive CtrlMessage without RunTearDown parameter."); } // 打印状态日志 Context.LogSession.Print(LogLevel.Info, Context.SessionId, "Teardown execution start."); sessionTaskEntity.InvokeTearDown(); // 打印状态日志 Context.LogSession.Print(LogLevel.Info, Context.SessionId, "Teardown execution over."); SendOverMessage(); Context.State = RuntimeState.Over; this.Next = null; }
private void SendSequenceStatusMessage(SequenceStatusInfo statusInfo) { StatusMessage statusMessage = null; switch (statusInfo.ReportType) { case StatusReportType.Start: statusMessage = new StatusMessage(MessageNames.ReportStatusName, _context.State, _context.SessionId) { Time = statusInfo.Time, Index = _context.MsgIndex }; statusMessage.InterestedSequence.Add(statusInfo.Sequence); statusMessage.Stacks.Add(statusInfo.Stack); statusMessage.SequenceStates.Add(RuntimeState.Running); statusMessage.Results.Add(statusInfo.Result); statusMessage.ExecutionTimes.Add(statusInfo.ExecutionTime); statusMessage.ExecutionTicks.Add(statusInfo.ExecutionTicks); statusMessage.Coroutines.Add(statusInfo.CoroutineId); _transceiver.SendMessage(statusMessage); break; case StatusReportType.Record: statusMessage = new StatusMessage(MessageNames.ReportStatusName, _context.State, _context.SessionId) { Time = statusInfo.Time, Index = _context.MsgIndex }; statusMessage.InterestedSequence.Add(statusInfo.Sequence); statusMessage.Stacks.Add(statusInfo.Stack); statusMessage.SequenceStates.Add(RuntimeState.Running); statusMessage.Results.Add(statusInfo.Result); statusMessage.WatchData = statusInfo.WatchDatas; statusMessage.ExecutionTimes.Add(statusInfo.ExecutionTime); statusMessage.ExecutionTicks.Add(statusInfo.ExecutionTicks); statusMessage.Coroutines.Add(statusInfo.CoroutineId); if (statusInfo.FailedInfo != null) { statusMessage.FailedInfo.Add(statusInfo.Sequence, statusInfo.FailedInfo.ToString()); } _transceiver.SendMessage(statusMessage); break; case StatusReportType.DebugHitted: DebugMessage debugMessage = new DebugMessage(MessageNames.BreakPointHitName, _context.SessionId, statusInfo.Stack, false) { Time = statusInfo.Time, Index = _context.MsgIndex }; // TODO add watch datas _transceiver.SendMessage(debugMessage); break; case StatusReportType.Failed: statusMessage = new StatusMessage(MessageNames.ReportStatusName, _context.State, _context.SessionId) { Time = statusInfo.Time, Index = _context.MsgIndex }; statusMessage.InterestedSequence.Add(statusInfo.Sequence); statusMessage.Stacks.Add(statusInfo.Stack); statusMessage.SequenceStates.Add(RuntimeState.Failed); statusMessage.Results.Add(statusInfo.Result); statusMessage.WatchData = statusInfo.WatchDatas; statusMessage.ExecutionTimes.Add(statusInfo.ExecutionTime); statusMessage.ExecutionTicks.Add(statusInfo.ExecutionTicks); statusMessage.Coroutines.Add(statusInfo.CoroutineId); if (statusInfo.FailedInfo != null) { statusMessage.FailedInfo.Add(statusInfo.Sequence, statusInfo.FailedInfo.ToString()); } _transceiver.SendMessage(statusMessage); break; case StatusReportType.Over: statusMessage = new StatusMessage(MessageNames.ReportStatusName, _context.State, _context.SessionId) { Time = statusInfo.Time, Index = _context.MsgIndex }; statusMessage.InterestedSequence.Add(statusInfo.Sequence); statusMessage.Stacks.Add(statusInfo.Stack); statusMessage.SequenceStates.Add(RuntimeState.Success); statusMessage.Results.Add(statusInfo.Result); statusMessage.WatchData = statusInfo.WatchDatas; statusMessage.ExecutionTimes.Add(statusInfo.ExecutionTime); statusMessage.ExecutionTicks.Add(statusInfo.ExecutionTicks); statusMessage.Coroutines.Add(statusInfo.CoroutineId); _transceiver.SendMessage(statusMessage); break; case StatusReportType.Error: statusMessage = new StatusMessage(MessageNames.ReportStatusName, _context.State, _context.SessionId) { Time = statusInfo.Time, Index = _context.MsgIndex }; statusMessage.InterestedSequence.Add(statusInfo.Sequence); statusMessage.Stacks.Add(statusInfo.Stack); statusMessage.SequenceStates.Add(RuntimeState.Error); statusMessage.Results.Add(statusInfo.Result); statusMessage.WatchData = statusInfo.WatchDatas; statusMessage.ExecutionTimes.Add(statusInfo.ExecutionTime); statusMessage.ExecutionTicks.Add(statusInfo.ExecutionTicks); statusMessage.Coroutines.Add(statusInfo.CoroutineId); if (statusInfo.FailedInfo != null) { statusMessage.FailedInfo.Add(statusInfo.Sequence, statusInfo.FailedInfo.ToString()); statusMessage.ExceptionInfo = null; } _transceiver.SendMessage(statusMessage); break; default: throw new NotImplementedException(); } }
public void Invoke(bool forceInvoke = false) { FailedInfo failedInfo = null; StepResult lastStepResult = StepResult.NotAvailable; StatusReportType finalReportType = StatusReportType.Failed; try { this.State = RuntimeState.Running; SequenceStatusInfo startStatusInfo = new SequenceStatusInfo(Index, _stepEntityRoot.GetStack(), StatusReportType.Start, RuntimeState.Running, StepResult.NotAvailable) { ExecutionTime = DateTime.Now, ExecutionTicks = -1, CoroutineId = RootCoroutineId }; _context.StatusQueue.Enqueue(startStatusInfo); StepTaskEntityBase stepEntity = _stepEntityRoot; do { stepEntity.Invoke(forceInvoke); } while (null != (stepEntity = stepEntity.NextStep)); SetResultState(out lastStepResult, out finalReportType, out failedInfo); } catch (TaskFailedException ex) { // 停止失败的step的计时 StepTaskEntityBase currentStep = StepTaskEntityBase.GetCurrentStep(Index, RootCoroutineId); currentStep?.EndTiming(); FillFinalExceptionReportInfo(ex, out finalReportType, out lastStepResult, out failedInfo); // 如果抛出TargetInvokcationException到当前位置则说明内部没有发送错误事件 if (null != currentStep && currentStep.Result == StepResult.NotAvailable) { currentStep.SetStatusAndSendErrorEvent(lastStepResult, failedInfo); } } catch (TestflowAssertException ex) { // 停止失败的step的计时 StepTaskEntityBase currentStep = StepTaskEntityBase.GetCurrentStep(Index, RootCoroutineId); currentStep?.EndTiming(); FillFinalExceptionReportInfo(ex, out finalReportType, out lastStepResult, out failedInfo); // 如果抛出TargetInvokcationException到当前位置则说明内部没有发送错误事件 if (null != currentStep && currentStep.Result == StepResult.NotAvailable) { currentStep.SetStatusAndSendErrorEvent(lastStepResult, failedInfo); } } catch (ThreadAbortException ex) { // 停止失败的step的计时 StepTaskEntityBase currentStep = StepTaskEntityBase.GetCurrentStep(Index, RootCoroutineId); currentStep?.EndTiming(); FillFinalExceptionReportInfo(ex, out finalReportType, out lastStepResult, out failedInfo); // Abort异常不会在内部处理,需要在外部强制抛出 currentStep?.SetStatusAndSendErrorEvent(lastStepResult, failedInfo); } catch (TargetInvocationException ex) { // 停止失败的step的计时 StepTaskEntityBase currentStep = StepTaskEntityBase.GetCurrentStep(Index, RootCoroutineId); currentStep?.EndTiming(); FillFinalExceptionReportInfo(ex.InnerException, out finalReportType, out lastStepResult, out failedInfo); // 如果抛出TargetInvokcationException到当前位置则说明内部没有发送错误事件 if (null != currentStep && currentStep.Result == StepResult.NotAvailable) { currentStep.SetStatusAndSendErrorEvent(lastStepResult, failedInfo); } } catch (TestflowLoopBreakException ex) { // 停止失败的step的计时 StepTaskEntityBase currentStep = StepTaskEntityBase.GetCurrentStep(Index, RootCoroutineId); currentStep?.EndTiming(); // 如果包含内部异常,则说明发生了运行时错误,记录错误信息。 if (null != ex.InnerException) { FillFinalExceptionReportInfo(ex.InnerException, out finalReportType, out lastStepResult, out failedInfo); // 如果抛出TargetInvokcationException到当前位置则说明内部没有发送错误事件 if (null != currentStep && currentStep.BreakIfFailed) { currentStep.SetStatusAndSendErrorEvent(lastStepResult, failedInfo); } } // 只是流程控制,记录结果信息后退出 else { SetResultState(out lastStepResult, out finalReportType, out failedInfo); } } catch (Exception ex) { // 停止失败的step的计时 StepTaskEntityBase currentStep = StepTaskEntityBase.GetCurrentStep(Index, RootCoroutineId); currentStep?.EndTiming(); FillFinalExceptionReportInfo(ex, out finalReportType, out lastStepResult, out failedInfo); // 如果抛出Exception到当前位置则说明内部没有发送错误事件 if (null != currentStep && currentStep.BreakIfFailed) { currentStep.SetStatusAndSendErrorEvent(lastStepResult, failedInfo); } } finally { StepTaskEntityBase currentStep = StepTaskEntityBase.GetCurrentStep(Index, RootCoroutineId); // 发送结束事件,包括所有的ReturnData信息 SequenceStatusInfo overStatusInfo = new SequenceStatusInfo(Index, currentStep.GetStack(), finalReportType, this.State, StepResult.Over, failedInfo) { ExecutionTime = DateTime.Now, CoroutineId = RootCoroutineId, ExecutionTicks = 0 }; overStatusInfo.WatchDatas = _context.VariableMapper.GetReturnDataValues(_sequence); this._context.StatusQueue.Enqueue(overStatusInfo); _context.VariableMapper.ClearSequenceVariables(_sequence); this._stepEntityRoot = null; // 将失败步骤职责链以后的step标记为null currentStep.NextStep = null; } }