using AddInPlugin;
|
using AddInPlugin.Setting;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
using Microsoft.Win32;
|
using OpenTap;
|
using OpenTap.Addin;
|
using OpenTap.Addin.Listener;
|
using OpenTap.Addin.Util;
|
using OpenTap.Plugins.BasicSteps;
|
using SeqEditor.Util;
|
using System.Collections.ObjectModel;
|
using System.Windows;
|
using System.Windows.Controls;
|
|
namespace OpenTapEditor;
|
/// <summary>
|
/// Interaction logic for SequencePanel.xaml
|
/// </summary>
|
[ObservableObject]
|
public partial class ExecutionPanel : UserControl, ITabItem, IStepRunStatus
|
{
|
private TestPlan Plan;
|
private TestPlanRun PlanRun;
|
private TapThread testPlanThread;
|
private string startedSeqName;
|
|
[ObservableProperty]
|
private ITestStep selectedTestStep;
|
|
[ObservableProperty]
|
private bool isRunning = false;
|
|
[ObservableProperty]
|
private bool hasChanged = false;
|
|
public string TabName
|
{
|
get
|
{
|
return $"Execution-{Plan?.Name}";
|
}
|
set
|
{
|
}
|
}
|
|
[ObservableProperty]
|
private RuningMode runingMode = RuningMode.Stop;
|
|
private ManualResetEvent SingleStepHandle = new ManualResetEvent(true);
|
|
public event EventHandler RunningFinished;
|
|
public ExecutionPanel(TestPlan plan, string seqName)
|
{
|
this.Plan = plan;
|
this.startedSeqName = seqName;
|
|
InitializeComponent();
|
treeView.Plan = plan;
|
}
|
|
private void VariableControl_SequenceChanged(object? sender, EventArgs e)
|
{
|
HasChanged = true;
|
}
|
|
private void ChildTestSteps_ChildStepsChanged(TestStepList senderList, TestStepList.ChildStepsChangedAction Action, ITestStep Object, int Index)
|
{
|
HasChanged = true;
|
}
|
|
private void ChildTestSteps_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
|
{
|
HasChanged = true;
|
}
|
|
private void Button_Click(object sender, RoutedEventArgs e)
|
{
|
var btn = (Button)sender;
|
switch (btn.Tag)
|
{
|
case "运行":
|
RunBtn();
|
break;
|
case "调试":
|
RunTestPlan(RuningMode.RunningInDebugMode);
|
break;
|
case "单步运行":
|
StepRuning();
|
break;
|
case "停止":
|
StopRunTestPlan();
|
break;
|
default:
|
break;
|
}
|
}
|
|
private void RunBtn()
|
{
|
if (IsRunning)
|
{
|
if (RuningMode == RuningMode.RunningInStepMode)
|
{
|
RuningMode = RuningMode.Running;
|
SingleStepHandle.Set();
|
return;
|
}
|
|
if (RuningMode == RuningMode.RunningInDebugModeButStep)
|
{
|
RuningMode = RuningMode.RunningInDebugMode;
|
SingleStepHandle.Set();
|
return;
|
}
|
|
if (RuningMode == RuningMode.RunningInDebugMode)
|
{
|
SingleStepHandle.Set();
|
return;
|
}
|
}
|
else
|
{
|
RunTestPlan(RuningMode.Running);
|
}
|
}
|
|
public void RunTestPlan(RuningMode mode)
|
{
|
try
|
{
|
/// 保存一下StationGlobals变量
|
try
|
{
|
StationGlobalsManager.WriteToLocal(UIStationGlobalsManager.Instance.Datasource);
|
}
|
catch (Exception ex)
|
{
|
|
}
|
IsRunning = true;
|
RuningMode = mode;
|
treeView.ComplatedIds.Clear();
|
treeView.UpdateStepStatus();
|
RunVars = null;
|
RunVarContext = null;
|
|
handledPlan.Clear();
|
handledPlan.Add(Plan);
|
Plan.BreakOffered += Plan_BreakOffered;
|
settingView.CanEdit = false;
|
runVariableControl.Visibility = Visibility.Visible;
|
var uiListener = new UIListener(SeqEditorUI.Instance.logControl, this);
|
|
testPlanThread = TapThread.Start(() =>
|
{
|
try
|
{
|
var s = ResultSettings.Current;
|
ResultSettings.Current.Add(uiListener);
|
if (StationSettings.Current.ReportType == ReportType.TXT)
|
{
|
ResultSettings.Current.Add(new TxtReportListener("Report"));
|
}
|
else
|
{
|
ResultSettings.Current.Add(new HtmlReportListener("Report"));
|
}
|
var res = ResultSettings.Current;
|
var run = Plan.Execute(startedSeqName, res, null, null, null);
|
}
|
catch (Exception ex)
|
{
|
SeqEditorUI.Log.Error("Start TestPlan Error. {0}", ex);
|
}
|
finally
|
{
|
ResultSettings.Current.Remove(uiListener);
|
RunVarContext?.Release();
|
Dispatcher.BeginInvoke(() =>
|
{
|
RunningFinished?.Invoke(this, new EventArgs());
|
RuningMode = RuningMode.Stop;
|
Plan.BreakOffered -= Plan_BreakOffered;
|
treeView.DebugStepId = Guid.Empty;
|
treeView.RunningStepId = Guid.Empty;
|
settingView.CanEdit = true;
|
IsRunning = false;
|
foreach (var handled in handledPlan)
|
{
|
handled.BreakOffered -= Plan_BreakOffered;
|
}
|
handledPlan.Clear();
|
});
|
}
|
}, "UI_Start");
|
}
|
catch (Exception ex)
|
{
|
SeqEditorUI.Log.Error("Run TestPlan Error. {0}", ex);
|
}
|
}
|
|
[ObservableProperty]
|
private RunningVarContext runVarContext;
|
|
[ObservableProperty]
|
private ObservableCollection<RunningVar> runVars;
|
|
private readonly List<TestPlan> handledPlan = new List<TestPlan>();
|
|
|
private string currentSeqId = null;
|
|
private void Plan_BreakOffered(object? sender, BreakOfferedEventArgs e)
|
{
|
try
|
{
|
var stepRun = e.TestStepRun;
|
var planRun = stepRun.testPlanRun;
|
var step = stepRun.CurrentStep;
|
var plan = step.Root;
|
var seqId = $"{plan.VisualPath}_{planRun.RunningSeqName}";
|
TestStepList list = plan.GetStepsByName(planRun.RunningSeqName);
|
|
Dispatcher.BeginInvoke(() =>
|
{
|
treeView.DebugStepId = e.TestStepRun.TestStepId;
|
if (RunVarContext == null)
|
{
|
RunVarContext = new RunningVarContext()
|
{
|
PlanRun = planRun
|
};
|
RunVarContext.Children = RunningVar.FromTest(RunVarContext, null, false, new ObservableCollection<TestVariable>() {
|
new TestVariable(){
|
Name = "Locals",
|
Type = TestVariableType.Container,
|
Children = list.Variables
|
},
|
new TestVariable(){
|
Name = "Parameters",
|
Type = TestVariableType.Container,
|
Children = list.Parameters
|
},
|
new TestVariable(){
|
Name = "FileGlobals",
|
Type = TestVariableType.Container,
|
Children = plan.Variables
|
},
|
new TestVariable(){
|
Name = "StationGlobals",
|
Type = TestVariableType.Container,
|
Children = UIStationGlobalsManager.Instance.Datasource,
|
}});
|
RunVars = RunVarContext.Children;
|
}
|
|
RunVarContext.Children[0].ContextName = list.SequenceName;
|
RunVarContext.Children[1].ContextName = list.SequenceName;
|
RunVarContext.Children[2].ContextName = plan.VisualPath;
|
|
if (currentSeqId != seqId)
|
{
|
RunVarContext.RefreshPlan(planRun, plan, list);
|
treeView.Datasource = list;
|
currentSeqId = seqId;
|
}
|
}).Wait();
|
|
if (step is SequenceCallStep scs)
|
{
|
//if (lastChildPlan != null)
|
//{
|
// lastChildPlan.BreakOffered -= Plan_BreakOffered;
|
//}
|
if (!handledPlan.Contains(scs.runningPlan))
|
{
|
scs.runningPlan.BreakOffered += Plan_BreakOffered;
|
handledPlan.Add(scs.runningPlan);
|
}
|
}
|
|
if (RuningMode == RuningMode.RunningInStepMode || RuningMode == RuningMode.RunningInDebugModeButStep)
|
{
|
SingleStepHandle.Reset();
|
WaitHandle.WaitAny(new[] { SingleStepHandle, testPlanThread.AbortToken.WaitHandle });
|
}
|
else if (RuningMode == RuningMode.RunningInDebugMode)
|
{
|
if (treeView.NeedBreak(e.TestStepRun.TestStepId))
|
{
|
SingleStepHandle.Reset();
|
WaitHandle.WaitAny(new[] { SingleStepHandle, testPlanThread.AbortToken.WaitHandle });
|
}
|
}
|
}
|
catch (Exception ex)
|
{
|
SeqEditorUI.Log.Error($"Plan_BreakOffered Error: {ex}");
|
}
|
}
|
|
private void StepRuning()
|
{
|
if (IsRunning && RuningMode != RuningMode.Running)
|
{
|
if (RuningMode == RuningMode.RunningInDebugMode)
|
{
|
RuningMode = RuningMode.RunningInDebugModeButStep;
|
}
|
SingleStepHandle.Set();
|
}
|
else
|
{
|
RunTestPlan(RuningMode.RunningInStepMode);
|
}
|
}
|
|
public void StopRunTestPlan()
|
{
|
testPlanThread?.Abort();
|
}
|
|
public bool TrySaveTestStep(Func<string, bool> check)
|
{
|
if (!string.IsNullOrEmpty(Plan.Path))
|
{
|
Plan.Save(Plan.Path);
|
HasChanged = false;
|
OnPropertyChanged(nameof(TabName));
|
return true;
|
}
|
return TrySaveAs(check);
|
}
|
|
public bool TrySaveAs(Func<string, bool> check)
|
{
|
SaveFileDialog sfd = new SaveFileDialog()
|
{
|
Filter = "Test Plan|*.TapPlan",
|
DefaultExt = ".TapPlan"
|
};
|
if (sfd.ShowDialog() == true)
|
{
|
if (check.Invoke(sfd.FileName))
|
{
|
Plan.Save(sfd.FileName);
|
HasChanged = false;
|
OnPropertyChanged(nameof(TabName));
|
return true;
|
}
|
}
|
return false;
|
}
|
|
private void treeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
|
{
|
if (e.NewValue != null)
|
{
|
settingView.UpdateSource((ITestStep)e.NewValue);
|
SelectedTestStep = (ITestStep)e.NewValue;
|
}
|
}
|
|
private void variableControl_SelectedSequenceChanged(object sender, TestStepList e)
|
{
|
treeView.Datasource = e;
|
settingView.Seq = e;
|
}
|
|
public void ComplatedStepId(Guid id)
|
{
|
Dispatcher.BeginInvoke(() =>
|
{
|
treeView.ComplatedIds[id] = true;
|
treeView.UpdateStepStatus();
|
});
|
}
|
|
public void CurrentStepId(Guid id)
|
{
|
Dispatcher.BeginInvoke(() =>
|
{
|
treeView.ComplatedIds.TryRemove(id, out _);
|
treeView.UpdateStepStatus();
|
treeView.RunningStepId = id;
|
});
|
}
|
|
public void Close()
|
{
|
RunVarContext = null;
|
RunVars = null;
|
settingView = null;
|
Plan = null;
|
PlanRun = null;
|
treeView.Unload();
|
}
|
}
|