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 Test(List <Point3d> expected, List <Point3d> actual, List <string> names, double tolerance) { ExpectedPoints = expected; ActualPoints = actual; Names = names; Tolerance = tolerance; _result = new List <string>(); _failedInfo = new List <string>(); string _failedString; bool _failedCurrent; if (ExpectedPoints.Count != ActualPoints.Count || ExpectedPoints.Count != Names.Count) { throw new ArgumentException("Expected list should match actual and names - check if all three lists have the same number of elements"); } _failed = false; for (int i = 0; i < ActualPoints.Count; i++) { _failedString = ""; _failedCurrent = false; if (Math.Abs(ExpectedPoints[i].X - ActualPoints[i].X) > Tolerance) { _failedString += "Check X coordinate;" + Environment.NewLine; _failedCurrent = true; } if (Math.Abs(ExpectedPoints[i].Y - ActualPoints[i].Y) > Tolerance) { _failedString += "Check Y coordinate;" + Environment.NewLine; _failedCurrent = true; } if (Math.Abs(ExpectedPoints[i].Z - ActualPoints[i].Z) > Tolerance) { _failedString += "Check Z coordinate;" + Environment.NewLine; _failedCurrent = true; } if (_failedCurrent) { Result.Add(Names[i] + ";FAILED"); FailedInfo.Add(Names[i] + Environment.NewLine + "Test Failed: Expected != Actual" + Environment.NewLine + ExpectedPoints[i] + " != " + ActualPoints[i] + Environment.NewLine + _failedString); _failed = true; } else { Result.Add(Names[i] + ";OK"); } } }
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); }
protected override void TaskErrorAction(Exception ex) { Context.LogSession.Print(LogLevel.Error, CommonConst.PlatformLogSession, "Test Generation failed."); TestGenMessage testGenFailMessage = new TestGenMessage(MessageNames.TestGenName, Context.SessionId, CommonConst.PlatformSession, GenerationStatus.Failed) { Index = Context.MsgIndex }; Context.UplinkMsgProcessor.SendMessage(testGenFailMessage, true); // 发送远程运行器生成失败的消息 RmtGenMessage rmtGenMessage = new RmtGenMessage(MessageNames.UpRmtGenMsgName, Context.SessionId, RunnerType.SequenceGroup); rmtGenMessage.Params.Add("MsgType", "Failed"); FailedInfo failedInfo = new FailedInfo(ex, FailedType.TestGenFailed); rmtGenMessage.Params.Add("FailedInfo", failedInfo.ToString()); Context.UplinkMsgProcessor.SendMessage(rmtGenMessage, true); }
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); } }
// 处理事件和消息。完成的工作有: // 更新SequenceStateHandle的状态、生成RuntimeStatusData并持久化、序列执行结束后生成SequenceResultData并持久化 #region 事件消息处理 public void AbortEventProcess(AbortEventInfo eventInfo) { // 如果序列已经结束或者当前序列为teardown序列,则不接收abort状态更新 if (ModuleUtils.IsOver(this.State) || this.SequenceIndex == CommonConst.TeardownIndex) { return; } if (eventInfo.IsRequest) { RefreshCommonStatus(eventInfo, RuntimeState.AbortRequested, StepResult.NotAvailable); } else { RefreshCommonStatus(eventInfo, RuntimeState.Abort, StepResult.Abort); RefreshExecutionStatus(null, 0); FailedInfo failedInfo = new FailedInfo(_stateManageContext.GlobalInfo.I18N.GetStr("UserAbort"), FailedType.Abort); UpdateSequenceTestResult(failedInfo, null); _eventDispatcher.RaiseEvent(Constants.SequenceOver, eventInfo.Session, _sequenceTestResult); WriteRuntimeStatusData(StepResult.Abort, string.Empty, new FailedInfo(eventInfo.FailInfo)); } }
public override void TaskAbortAction() { TestGenMessage testGenMessage = new TestGenMessage(MessageNames.TestGenName, Context.SessionId, CommonConst.PlatformLogSession, GenerationStatus.Failed) { Index = Context.MsgIndex }; Context.UplinkMsgProcessor.SendMessage(testGenMessage, true); // 发送远程运行器生成失败的消息 RmtGenMessage rmtGenMessage = new RmtGenMessage(MessageNames.UpRmtGenMsgName, Context.SessionId, RunnerType.SequenceGroup); rmtGenMessage.Params.Add("MsgType", "Failed"); FailedInfo failedInfo = new FailedInfo(Context.I18N.GetStr("OperationAborted"), FailedType.Abort); rmtGenMessage.Params.Add("FailedInfo", failedInfo.ToString()); Context.UplinkMsgProcessor.SendMessage(rmtGenMessage, true); base.TaskAbortAction(); }
private bool HandleControlMessage(ControlMessage message) { int session = message.Id; string name = message.Name; switch (name) { case MessageNames.CtrlAbort: bool abortSuccess = bool.Parse(message.Params["AbortSuccess"]); AbortEventInfo abortEventInfo = new AbortEventInfo(session, false, abortSuccess); // 如果不包含,说明取消成功 if (!abortSuccess && message.Params.ContainsKey("Message")) { abortEventInfo.FailInfo = message.Params["Message"]; } else { abortEventInfo.FailInfo = FailedInfo.GetFailedStr(_globalInfo.I18N.GetStr("UserAbort"), FailedType.Abort); } _globalInfo.EventQueue.Enqueue(abortEventInfo); _testsMaintainer.FreeHost(session); // 如果所有的都已经结束,则修改状态机状态 if (0 == _testsMaintainer.TestContainers.Count) { _globalInfo.StateMachine.State = RuntimeState.Abort; } // 同步释放,每个Session的停止都是同步执行的。 _abortBlocker?.Free(Constants.AbortState); break; default: throw new InvalidOperationException(); } return(true); }
public SequenceStatusInfo(int sequence, CallStack stack, StatusReportType type, RuntimeState sequenceState, StepResult result, FailedInfo failedInfo = null) { this.SequenceState = sequenceState; this.Sequence = sequence; this.Stack = stack; this.ReportType = type; this.FailedInfo = failedInfo; this.Time = DateTime.Now; this.Result = result; }
private void ProcessQueuedItems(object ignored) { while (true) { JobMessage job; lock (_jobs) { if (_jobs.Count == 0) { _delegateQueuedOrRunning = false; break; } job = _jobs.Dequeue(); } JobUtilExtensions.RunSync(async() => { try { var properies = new Dictionary <string, object> { [JobConstant.LOGGER_SCOPE_JOBID_KEY] = job.Id, [JobConstant.LOGGER_SCOPE_JOBLOGID_KEY] = job.LogId, [JobConstant.LOGGER_SCOPE_JOBAREA_KEY] = JobConstant.LOGGER_SCOPE_JOBAREA_VALUE }; using (_logger.BeginScope(properies)) { var result = await _sender.Execute(job); job.CallBackCode = result.Code; if (result.Code == JobConstant.HTTP_FAIL_CODE) { _logger.LogError($"执行失败. Id:{job.Id}, Msg: {result.Msg}"); job.Reason = result.Msg; } else { job.Reason = result.Content; } } await _sender.CallBack(new List <JobMessage>() { job }); } catch (Exception ex) { var failedInfo = new FailedInfo() { ServiceProvider = _serviceProvider, Exception = ex, Job = job, Message = $"执行异常. Id:{job.Id}" }; _options?.FailedCallback?.Invoke(failedInfo); _logger.LogError(ex, failedInfo.Message); } }); } }
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; }
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; } }