using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Xml.Serialization;
using QC.CTDS.DM.ApplicationsManager;
using QC.CTDS.DM.DataStructures.InputDataStructure;
using QC.CTDS.DM.DataStructures.LimitDescriptorDataStructure;
using QC.QsprShared.Dialogs;
using QC.QsprShared.Trace;
using QC.QsprTestObjects.Loops;
using QC.QsprTestObjects.Parameters;
using QC.QsprTestObjects.Registry;
using QC.QsprTestObjects.TestConditions;
using QC.QsprTestObjects.Tests.DotNet;
using QC.QsprTestObjects.Tests.Hive;
using QC.QsprTestObjects.Tests.TestCase;
using QC.QTMDotNetKernel.Handlers;
using QC.QTMDotNetKernel.Registry;
using QC.QTMDotNetKernelInterface;
using QC.QTMInterface;

namespace QC.QsprTestObjects.Tests.Base;

[Serializable]
public abstract class BaseTest : INotifyPropertyChanged
{
	public const int iPassed = 1;

	public const int iFailed = 0;

	public const int iException = -1;

	public const int iFakeResult = int.MaxValue;

	public const string TEST = "Test";

	public const string TEST_PATH_SEPARATOR = ".";

	public const string UNIQUE_PATH_SEPARATOR = "|";

	protected TestProperties testProperties;

	protected string name;

	protected string index;

	protected string originalIndex;

	protected FolderTest parent;

	protected RootTest root;

	protected TestRuntimeAttributes runtimeAttributes = new TestRuntimeAttributes();

	[XmlIgnore]
	public bool preRequisiteFailed;

	private bool treeSaving;

	protected MessageDelegate msgDelegate => Root.Scheduler.TestMsgBroadCaster.msgDelegate;

	public virtual TestResult CurrentResult
	{
		get
		{
			if (RuntimeAttributes.Exception)
			{
				return TestResult.Exception;
			}
			if (RuntimeAttributes.Failed)
			{
				return TestResult.Failed;
			}
			if (RuntimeAttributes.Skipped)
			{
				return TestResult.Skipped;
			}
			return TestResult.Passed;
		}
	}

	[XmlAttribute("NodeType")]
	[Browsable(false)]
	public virtual string NodeType
	{
		get
		{
			return "Test";
		}
		set
		{
		}
	}

	[XmlIgnore]
	public virtual TestProperties Properties
	{
		get
		{
			testProperties.Owner = this;
			return testProperties;
		}
		set
		{
			testProperties.Owner = this;
			testProperties = value;
		}
	}

	public virtual string RealName => name;

	public virtual string Index
	{
		get
		{
			return index;
		}
		set
		{
			try
			{
				if (!(index != value))
				{
					return;
				}
				if (Properties != null)
				{
					foreach (string loopLink in Properties.LoopLinks)
					{
						FindLoopParent(loopLink)?.Properties.RenameLoopLink(index, value);
					}
					if (Properties.LoopLinks.Count == 0 && Properties.Scenarios != null && Properties.Scenarios.LoopConditions.Count > 0)
					{
						foreach (LoopCondition loopCondition in Properties.Scenarios.LoopConditions)
						{
							loopCondition.TestIndex = value;
						}
					}
				}
				index = value;
				Properties.TestIndexCopy = index;
			}
			catch (Exception ex)
			{
				TraceMessage.Write(ToString(), "Index " + Properties.TestName + " " + ex.Message, TraceMessageType.Exception);
			}
		}
	}

	public virtual string OriginalIndex
	{
		get
		{
			if (originalIndex == null)
			{
				return index;
			}
			return originalIndex;
		}
		set
		{
			originalIndex = value;
		}
	}

	[XmlIgnore]
	public virtual bool TreeSaving
	{
		get
		{
			return treeSaving;
		}
		set
		{
			if (treeSaving != value)
			{
				treeSaving = value;
				Properties.Parameters.SetTreeSaving(value);
			}
		}
	}

	[XmlIgnore]
	public virtual RootTest Root
	{
		get
		{
			return root;
		}
		set
		{
			root = value;
			if (Properties.Scenarios != null && Properties.Scenarios.Count > 0 && Properties.Scenarios.Condition != null)
			{
				foreach (BaseCondition condition in Properties.Scenarios.Condition.Conditions)
				{
					condition.root = Root;
				}
			}
			if (Properties.PreCondition != null && Properties.PreCondition.Conditions != null)
			{
				foreach (BaseCondition condition2 in Properties.PreCondition.Conditions)
				{
					condition2.root = Root;
				}
			}
			if (Properties.PostCondition == null || Properties.PostCondition.Conditions == null)
			{
				return;
			}
			foreach (BaseCondition condition3 in Properties.PostCondition.Conditions)
			{
				condition3.root = Root;
			}
		}
	}

	[XmlIgnore]
	public virtual FolderTest Parent
	{
		get
		{
			return parent;
		}
		set
		{
			if (parent != value)
			{
				parent = value;
				if (parent != null)
				{
					Root = parent.Root;
				}
			}
		}
	}

	[XmlIgnore]
	public string UltraTreeNodePath
	{
		get
		{
			string text = "";
			for (BaseTest baseTest = this; baseTest != null; baseTest = baseTest.Parent)
			{
				text = baseTest.Properties.TestName + "." + text;
			}
			return text.Substring(0, text.Length - 1);
		}
	}

	[XmlIgnore]
	public string TestPath => GetTestPath(uniquePath: false);

	[XmlIgnore]
	public string UniqueTestPath => GetTestPath(uniquePath: true);

	[XmlIgnore]
	public string UniqueTestPathWithoutIndex => GetTestPath(uniquePath: true, includeIndex: false);

	[DefaultValue(false)]
	[Browsable(false)]
	public bool IsTestStep { get; set; }

	[Browsable(false)]
	public TestCaseTest TestCase
	{
		get
		{
			if (this is TestCaseTest)
			{
				return this as TestCaseTest;
			}
			return GetParentTestCase();
		}
	}

	[XmlIgnore]
	public virtual TestRuntimeAttributes RuntimeAttributes
	{
		get
		{
			return runtimeAttributes;
		}
		set
		{
			runtimeAttributes = value;
		}
	}

	[XmlIgnore]
	public bool CanRename
	{
		get
		{
			if (!(this is TestCaseTest))
			{
				return !(Properties is TestPlanProperties);
			}
			return false;
		}
	}

	[XmlIgnore]
	public TestUserInterfaceProperties TestUserInterfaceProperties { get; set; }

	[field: NonSerialized]
	public event PropertyChangedEventHandler PropertyChanged;

	public BaseTest()
	{
		name = "Test";
		index = Guid.NewGuid().ToString();
		TestUserInterfaceProperties = new TestUserInterfaceProperties(this);
	}

	public BaseTest(string name)
	{
		this.name = name;
		index = Guid.NewGuid().ToString();
		Properties.RealName = this.name;
		Properties.TestName = this.name;
		Properties.TestIndexCopy = index;
		TestUserInterfaceProperties = new TestUserInterfaceProperties(this);
	}

	public BaseTest(string name, string targetName, RootTest root)
	{
		this.name = name;
		index = Guid.NewGuid().ToString();
		Properties.TestIndexCopy = index;
		Properties.RealName = this.name;
		Properties.TestName = this.name;
		Properties.TargetName = targetName;
		Root = root;
		Properties.Parameters = ((QTMRegistry)Root.Scheduler.QTMData.theRegistry).GetParameters(this);
		TestProperties testProperties = ((QTMRegistry)Root.Scheduler.QTMData.theRegistry).GetTestProperties(this);
		Properties.Description = testProperties.Description;
		Properties.TestErrorCode = testProperties.TestErrorCode;
		Properties.SkipWhenLinked = testProperties.SkipWhenLinked;
		Properties.BookKeeping = testProperties.BookKeeping;
		Properties.CanAddToTestPlan = testProperties.CanAddToTestPlan;
		Properties.IsSetupTestStep = testProperties.IsSetupTestStep;
		Properties.IsTearDownTestStep = testProperties.IsTearDownTestStep;
		TestUserInterfaceProperties = new TestUserInterfaceProperties(this);
	}

	public virtual BaseTest Copy(BaseTest b)
	{
		b.name = RealName;
		b.Index = index;
		b.Parent = Parent;
		Properties.TestIndexCopy = index;
		return this;
	}

	public virtual int GetSetNumberOfTests()
	{
		Properties.NumberOfTests = 1;
		return Properties.NumberOfTests;
	}

	public virtual void RemoveRegistrationInformation()
	{
		Properties.NodeRID = -1L;
	}

	public virtual int QueueTestCount(int depth, ArrayList list)
	{
		try
		{
			int num = 0;
			num = ((depth == 1) ? 1 : ((Properties.CheckStateTest == CheckState.Checked && !Properties.ToolTest) ? 1 : ((Parent.RuntimeAttributes.Tool && Properties.CheckStateTest == CheckState.Checked) ? 1 : 0)));
			if (num > 0)
			{
				MsgData msgData = default(MsgData);
				msgData.msgType = TestMsgType.OnEnqueueTest;
				msgData.TestFullPath = TestPath;
				msgData.TestIndex = Index;
				list.Add(msgData);
			}
			return num;
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "QueueTestCount " + ex.Message, TraceMessageType.Exception);
			return 0;
		}
	}

	public virtual bool UpdateLoopValues()
	{
		bool flag = true;
		try
		{
			if (Properties.Scenarios != null)
			{
				int num = 1;
				foreach (LoopCondition loopCondition in Properties.Scenarios.LoopConditions)
				{
					string errorMessage = "";
					if (!loopCondition.UpdateLoopValues(Root, out errorMessage, Root.Scheduler.GlobalStatus.TreeName))
					{
						AppMessageDialog.Show("Loop values could not be updated for Test: " + Properties.TestName + "\n" + errorMessage, "QSPR - Message Center", MessageBoxButtons.OK, MessageBoxIcon.Hand, DialogResult.OK, MessageDialogType.Warning);
						flag = false;
						break;
					}
					if (loopCondition.LoopValues.Count > num)
					{
						num = loopCondition.LoopValues.Count;
					}
				}
				int count = Properties.Scenarios.DontRunCondition.Count;
				int num2 = num;
				if (num2 != count)
				{
					ArrayList arrayList = (ArrayList)Properties.Scenarios.ConditionCheck.Clone();
					ArrayList arrayList2 = (ArrayList)Properties.Scenarios.DontRunCondition.Clone();
					ArrayList arrayList3 = (ArrayList)Properties.Scenarios.Descriptions.Clone();
					Properties.Scenarios.ConditionCheck = new ArrayList();
					Properties.Scenarios.DontRunCondition = new ArrayList();
					Properties.Scenarios.Descriptions = new ArrayList();
					for (int i = 0; i < num2; i++)
					{
						if (i < count)
						{
							Properties.Scenarios.ConditionCheck.Add(arrayList[i]);
							Properties.Scenarios.DontRunCondition.Add(arrayList2[i]);
							Properties.Scenarios.Descriptions.Add(arrayList3[i]);
						}
						else
						{
							Properties.Scenarios.ConditionCheck.Add(true);
							Properties.Scenarios.DontRunCondition.Add("");
							Properties.Scenarios.Descriptions.Add("");
						}
					}
				}
				Properties.Scenarios.ClearBottomEmptyRows();
				if (!flag)
				{
					return flag;
				}
			}
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "UpdateLoopValues " + Properties.TestName + " " + ex.Message, TraceMessageType.Exception);
		}
		return flag;
	}

	public abstract BaseTest Clone();

	public abstract void Add(BaseTest baseTest);

	public abstract void Remove(BaseTest baseTest);

	public abstract void Display(int indent);

	public abstract void Insert(BaseTest baseTest, int index);

	public virtual void Clear()
	{
	}

	public virtual bool SyncParameters(ArrayList failedList, bool includeDescription = false)
	{
		TraceMessage.Write(ToString(), "SyncParameters " + Properties.TestName, TraceMessageType.Trace);
		try
		{
			if (LoadContainer())
			{
				ParameterCollection parameters = ((QTMRegistry)Root.Scheduler.QTMData.theRegistry).GetParameters(this);
				if (parameters.SyncParameters(Properties.Parameters, includeDescription))
				{
					Properties.Parameters = parameters;
					return true;
				}
			}
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "SyncParameters " + Properties.TestName + " " + ex.Message, TraceMessageType.Exception);
		}
		failedList.Add(Properties.TestName);
		return false;
	}

	public virtual bool SyncTestCaseProperties(bool includeDescription)
	{
		TraceMessage.Write(ToString(), "SyncTestCaseProperties " + Properties.TestName, TraceMessageType.Trace);
		try
		{
			if (this is HiveTest)
			{
				return false;
			}
			if (LoadContainer())
			{
				TestProperties testProperties = ((QTMRegistry)Root.Scheduler.QTMData.theRegistry).GetTestProperties(this);
				Properties.IsSetupTestStep = testProperties.IsSetupTestStep;
				Properties.IsTearDownTestStep = testProperties.IsTearDownTestStep;
				Properties.CanAddToTestPlan = testProperties.CanAddToTestPlan;
				Properties.IsManual = testProperties.IsManual;
				if (includeDescription)
				{
					Properties.Description = testProperties.Description;
				}
				return true;
			}
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "SyncTestCaseProperties " + Properties.TestName + " " + ex.Message, TraceMessageType.Exception);
		}
		return false;
	}

	public virtual bool ResetRetryCount()
	{
		try
		{
			if (Properties.RetryCount > 0)
			{
				int retryCount = Properties.RetryCount;
				Properties.RetryCount = 0;
				Properties.TestIndexCopy = index;
				Properties.RetryCount = retryCount;
			}
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "ResetRetryCount " + Properties.TestName + " " + ex.Message, TraceMessageType.Exception);
			return false;
		}
		return true;
	}

	public virtual bool ResetComment()
	{
		try
		{
			Properties.Comment = "";
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "ResetComment " + Properties.TestName + " " + ex.Message, TraceMessageType.Exception);
			return false;
		}
		return true;
	}

	public abstract bool StartTest();

	public virtual void OnPropChanged(PropertyValueChangedEventArgs e)
	{
		Properties.OnPropChanged(e);
	}

	protected bool LoadContainer()
	{
		try
		{
			if (Root.Scheduler.GlobalStatus.SimulatorMode && !(this is HiveTest))
			{
				return true;
			}
			return ((QTMRegistry)Root.Scheduler.QTMData.theRegistry).LoadContainer(Properties.RealName, Properties.TargetName, newContainer: false);
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "LoadContainer failed, " + ex.Message, TraceMessageType.Exception);
		}
		return false;
	}

	public void StopTest()
	{
		TraceMessage.Write(ToString(), "ENTER: BaseTest.StopTest()", TraceMessageType.Trace);
		QTMTarget target = ((QTMRegistry)Root.Scheduler.QTMData.theRegistry).GetTarget(Properties.TargetName);
		target.StopTest(this);
		TraceMessage.Write(ToString(), "EXIT: BaseTest.StopTest()", TraceMessageType.Trace);
	}

	public virtual void StopQTMTest()
	{
	}

	public virtual bool CanTestRun(TestRuntimeAttributes folderAttributes)
	{
		TraceMessage.Write(ToString(), "ENTER: BaseTest.CanTestRun()", TraceMessageType.Trace);
		TraceMessage.Write(ToString(), string.Concat("CanTestRun FOLDER -- Tool:", folderAttributes.Tool, " RightClick:", folderAttributes.RightClickTest, " SOE:", folderAttributes.StopOnError, " Exception:", folderAttributes.Exception), TraceMessageType.Trace);
		TraceMessage.Write(ToString(), "CanTestRun CheckState:" + Properties.CheckStateTest, TraceMessageType.Trace);
		TraceMessage.Write(ToString(), "CanTestRun GlobalStatus:" + Root.Scheduler.GlobalStatus.GLOBAL_STATUS, TraceMessageType.Trace);
		bool flag = false;
		try
		{
			if (preRequisiteFailed && !Root.Scheduler.IsInRerunMode)
			{
				if (Properties.CheckStateTest == CheckState.Checked)
				{
					ArrayList arrayList = new ArrayList();
					MsgData msgData = default(MsgData);
					msgData.TestFullPath = TestPath;
					msgData.TestIndex = Index;
					msgData.msgType = TestMsgType.OnTestResult;
					arrayList.Add(msgData);
					TestMessage message = default(TestMessage);
					message.Message = TestPath;
					message.Message = Properties.TestName;
					message.NodeRID = Properties.NodeRID;
					message.Object = arrayList;
					message.Result = TestResult.Failed;
					message.ResultDetails.ErrDescription = "Prerequisite Tests Failed.";
					message.TestIndex = Index;
					string gvValue = "";
					Root.Scheduler.Env.GlobalVariable.GetGlobalVariable("SN", out gvValue);
					message.SerialNumber = gvValue;
					RuntimeAttributes.TestStartTime = DateTime.Now;
					RuntimeAttributes.TestStopTime = DateTime.Now;
					msgDelegate(TestMsgType.OnTestSkipped, message);
					Root.Scheduler.AddFailedTest(this);
				}
				return false;
			}
			if (preRequisiteFailed && Root.Scheduler.IsInRerunMode && Root.Scheduler.GetFailedTests().Contains(this))
			{
				ArrayList arrayList2 = new ArrayList();
				MsgData msgData2 = default(MsgData);
				msgData2.TestFullPath = TestPath;
				msgData2.TestIndex = Index;
				msgData2.msgType = TestMsgType.OnTestResult;
				arrayList2.Add(msgData2);
				TestMessage message2 = default(TestMessage);
				message2.Message = TestPath;
				message2.Message = Properties.TestName;
				message2.NodeRID = Properties.NodeRID;
				message2.Object = arrayList2;
				message2.Result = TestResult.Failed;
				message2.ResultDetails.ErrDescription = "Prerequisite Tests Failed.";
				message2.TestIndex = Index;
				string gvValue2 = "";
				Root.Scheduler.Env.GlobalVariable.GetGlobalVariable("SN", out gvValue2);
				message2.SerialNumber = gvValue2;
				RuntimeAttributes.TestStartTime = DateTime.Now;
				RuntimeAttributes.TestStopTime = DateTime.Now;
				msgDelegate(TestMsgType.OnTestSkipped, message2);
				Root.Scheduler.AddFailedTest(this);
				return false;
			}
			if (Properties.MustRunTest)
			{
				return true;
			}
			if (Properties.TreeMustRun && Properties.CheckStateTest == CheckState.Checked)
			{
				flag = true;
			}
			if (Root.Scheduler.IsInRerunMode && !ShouldRerun())
			{
				return false;
			}
			if (Properties.CheckStateTest == CheckState.Checked)
			{
				bool alwaysPerformMustRunTests = Root.RootProperties.AlwaysPerformMustRunTests;
				if ((Root.Scheduler.GlobalStatus.Stop || Parent.AbortFolder) && (!Properties.TreeMustRun || !alwaysPerformMustRunTests))
				{
					flag = false;
				}
				else if (folderAttributes.StopOnError > StopOnErrorTypes.None || folderAttributes.PostConditionAction > PostConditionActions.None)
				{
					if (Properties.TreeMustRun && folderAttributes.PostConditionAction != PostConditionActions.RestartTestTreeWithoutMustRuns)
					{
						flag = true;
					}
					else if (Properties.FolderMustRun && folderAttributes.Failed && folderAttributes.PostConditionAction != PostConditionActions.RestartTestTreeWithoutMustRuns)
					{
						flag = true;
					}
					else if (folderAttributes.StopOnError == StopOnErrorTypes.PauseTestTree || folderAttributes.PostConditionAction == PostConditionActions.PauseTestTree)
					{
						flag = true;
					}
					else if (ParentHasRetry(Parent))
					{
						flag = true;
					}
				}
				else if (Root.Scheduler.GlobalStatus.BranchOnError)
				{
					if (Index.Trim() == Root.Scheduler.GlobalStatus.BranchOnTestIndex.Trim() || OriginalIndex.Trim() == Root.Scheduler.GlobalStatus.BranchOnTestIndex.Trim())
					{
						flag = true;
					}
					else if (Properties.TreeMustRun)
					{
						flag = true;
					}
					else if (Properties.FolderMustRun && Properties.CheckStateTest == CheckState.Checked && folderAttributes.Failed)
					{
						flag = true;
					}
				}
				else if (folderAttributes.Tool)
				{
					flag = true;
				}
				else if (Properties.ToolTest && folderAttributes.RightClickTest)
				{
					flag = true;
				}
				else if (!Properties.ToolTest)
				{
					flag = true;
				}
			}
			else if (folderAttributes.RightClickTest)
			{
				flag = true;
			}
			bool flag2 = false;
			if (Properties.PreCondition != null && flag && Properties.PreCondition.Enabled && Properties.PreCondition.IsConditionMet(new ParameterCollection(), TestResult.Passed))
			{
				flag = false;
				flag2 = true;
			}
			if ((flag2 || Properties.CheckStateTest != CheckState.Checked) && GetRootTest().RootProperties.LogSkippedResults)
			{
				ArrayList arrayList3 = new ArrayList();
				MsgData msgData3 = default(MsgData);
				msgData3.TestFullPath = TestPath;
				msgData3.TestIndex = Index;
				msgData3.msgType = TestMsgType.OnTestSkipped;
				arrayList3.Add(msgData3);
				TestMessage message3 = default(TestMessage);
				message3.Message = TestPath;
				message3.Message = Properties.TestName;
				message3.NodeRID = Properties.NodeRID;
				message3.Object = arrayList3;
				message3.Result = TestResult.Skipped;
				if (Properties.CheckStateTest == CheckState.Unchecked)
				{
					message3.ResultDetails.ErrDescription = "UnChecked";
				}
				message3.TestIndex = Index;
				string gvValue3 = "";
				Root.Scheduler.Env.GlobalVariable.GetGlobalVariable("SN", out gvValue3);
				message3.SerialNumber = gvValue3;
				RuntimeAttributes.TestStartTime = DateTime.Now;
				RuntimeAttributes.TestStopTime = DateTime.Now;
				msgDelegate(TestMsgType.OnTestSkipped, message3);
			}
			else if (!flag)
			{
				ArrayList arrayList4 = new ArrayList();
				MsgData msgData4 = default(MsgData);
				msgData4.msgType = TestMsgType.OnDequeueTest;
				msgData4.TestFullPath = TestPath;
				msgData4.TestIndex = Index;
				arrayList4.Add(msgData4);
				TestMessage message4 = default(TestMessage);
				message4.Message = TestPath;
				message4.NodeRID = Properties.NodeRID;
				message4.Object = arrayList4;
				message4.Result = TestResult.Passed;
				message4.TestIndex = Index;
				msgDelegate(TestMsgType.OnDequeueTest, message4);
			}
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "CanTestRun " + ex.Message, TraceMessageType.Exception);
			return false;
		}
		TraceMessage.Write(ToString(), "EXIT: BaseTest.CanTestRun() returning " + flag, TraceMessageType.Trace);
		return flag;
	}

	public bool ShouldRerun()
	{
		if (Root.Scheduler.GetFailedTests().Contains(this))
		{
			return true;
		}
		if (Root.Scheduler.GetPreRequisiteTest().Contains(this))
		{
			return true;
		}
		if (Root.Scheduler.GetMustRunTests().Contains(this))
		{
			return true;
		}
		if (TestCase != null && Root.Scheduler.GetFailedTests().Contains(TestCase))
		{
			return true;
		}
		if (this.IsInSetupFolder() || this.IsInCleanupFolder())
		{
			return true;
		}
		if (Properties.CanAddToTestPlan)
		{
			return true;
		}
		if (this is FolderTest && !(this is TestCaseTest))
		{
			if (HasCanAddToTestPlanChild(this as FolderTest))
			{
				return true;
			}
			foreach (BaseTest test in (this as FolderTest).TestList)
			{
				if (test.ShouldRerun())
				{
					return true;
				}
			}
		}
		if (this is FolderTest)
		{
			if (Properties.FolderMustRun && Root.Scheduler.ContainsFailedTests(Parent))
			{
				return true;
			}
		}
		else if (Properties.FolderMustRun && (Root.Scheduler.ContainsFailedTests(Parent) || (Parent.Properties.FolderMustRun && Root.Scheduler.ContainsFailedTests(Parent.Parent))))
		{
			return true;
		}
		return false;
	}

	private bool HasCanAddToTestPlanChild(FolderTest folderTest)
	{
		foreach (BaseTest test in folderTest.TestList)
		{
			if (test.Properties.CanAddToTestPlan)
			{
				return true;
			}
			if (test is FolderTest && HasCanAddToTestPlanChild(test as FolderTest))
			{
				return true;
			}
		}
		return false;
	}

	public bool ParentHasRetry(BaseTest FolderNode)
	{
		if (FolderNode is RootTest || FolderNode.Parent == null)
		{
			return false;
		}
		if (FolderNode.Parent.Properties.RetryCount > 0)
		{
			return true;
		}
		return ParentHasRetry(FolderNode.Parent);
	}

	public int ParentRetryValue(BaseTest FolderNode)
	{
		if (FolderNode is RootTest || FolderNode.Parent == null)
		{
			return -1;
		}
		if (FolderNode is TestCaseTest)
		{
			return -1;
		}
		if (FolderNode.Parent.Properties.RetryCount > 0)
		{
			if (FolderNode.Parent is TestCaseTest)
			{
				return -1;
			}
			return FolderNode.Parent.Properties.RetryCount;
		}
		return ParentRetryValue(FolderNode.Parent);
	}

	public int RetryValue(BaseTest FolderNode)
	{
		if (FolderNode is RootTest || FolderNode.Parent == null)
		{
			return -1;
		}
		if (FolderNode.Properties.RetryCount > 0)
		{
			return FolderNode.Properties.RetryCount;
		}
		return -1;
	}

	public bool IsInRetry()
	{
		if (this is RootTest || Parent == null)
		{
			return false;
		}
		if (Properties.RetryCount > 0)
		{
			string loopName = (Properties.Scenarios.LoopConditions[0] as LoopCondition).LoopName;
			int retryCount = Properties.RetryCount;
			string[] separator = new string[1] { "__" };
			string[] separator2 = new string[1] { "_._" };
			string[] array = Parent.Root.Scheduler.GlobalStatus.LoopDetails.Split(separator2, StringSplitOptions.None);
			string[] array2 = array;
			foreach (string text in array2)
			{
				if (!string.IsNullOrWhiteSpace(text))
				{
					string[] array3 = text.Split(separator, StringSplitOptions.None);
					string text2 = array3[0];
					string s = array3[1];
					if (text2 == loopName && int.Parse(s) < retryCount)
					{
						return true;
					}
				}
			}
		}
		return Parent.IsInRetry();
	}

	public virtual void GetAllParamInfo(string realName, string containerName, ref object objParameters)
	{
	}

	public virtual void GetResultsParamInfo(ref object obj)
	{
	}

	public abstract void RunQTMTest(string testName, string containerName, ref object objParameters, ref object objProperties);

	public FolderTest GetLinkRootFolder()
	{
		try
		{
			if (this != null)
			{
				if (this is FolderTest && ((FolderTest)this).FolderProperties.LinkRoot)
				{
					return (FolderTest)this;
				}
				if (Parent != null)
				{
					return Parent.GetLinkRootFolder();
				}
				return null;
			}
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "GetLinkRootFolder " + ex.Message, TraceMessageType.Exception);
		}
		return null;
	}

	public RootTest GetRootTest()
	{
		RootTest result = null;
		if (this is RootTest)
		{
			result = (RootTest)this;
		}
		else if (parent != null)
		{
			result = parent.GetRootTest();
		}
		else if (this is FolderTest && ((FolderTest)this).TestList.Count > 0)
		{
			result = ((FolderTest)this).TestList[0].GetRootTest();
		}
		return result;
	}

	public void RunTestInteractive(string testName, ref object objParameters)
	{
		object objProperties = string.Empty;
		RunTest(testName, ref objParameters, ref objProperties);
	}

	protected void RunTest(string testName, ref object objParameters, ref object objProperties)
	{
		try
		{
			TraceMessage.WriteAlways(ToString(), "ENTER: BaseTest.RunTest(" + testName + ")", TraceMessageType.Trace);
			Root.Scheduler.mutTest.WaitOne();
			TraceMessage.WriteAlways(ToString(), "Updating loop iterations for: " + testName, TraceMessageType.Trace);
			UpdateLoopIterations();
			if (!Root.Scheduler.GlobalStatus.SimulatorMode)
			{
				MsgData msgData = CreateRunMsgData();
				bool flag = Root.RootProperties.TreeType == TreeTypes.TestPlan;
				TraceMessage.WriteAlways(ToString(), "Setting current test information for: " + testName, TraceMessageType.Trace);
				if (flag)
				{
					((QTMRegistry)Root.Scheduler.QTMData.theRegistry).SetGlobalVariable("CurrentTestParentRetryInfo", ParentRetryValue(this));
					((QTMRegistry)Root.Scheduler.QTMData.theRegistry).SetGlobalVariable("CurrentTestRetryInfo", RetryValue(this));
				}
				((QTMRegistry)Root.Scheduler.QTMData.theRegistry).SetGlobalVariable("CurrentTestDetails", msgData);
				if (flag)
				{
					if (TestCase != null)
					{
						TraceMessage.WriteAlways(ToString(), "Setting testcase name GV to: " + TestCase.Properties.TestName, TraceMessageType.Trace);
						Root.Scheduler.Env.GlobalVariable.SetGlobalVariable("TESTCASE_NAME", TestCase.Properties.TestName);
					}
					else
					{
						TraceMessage.WriteAlways(ToString(), "Clearing testcase name GV", TraceMessageType.Trace);
						Root.Scheduler.Env.GlobalVariable.SetGlobalVariable("TESTCASE_NAME", "");
					}
				}
				if (!Root.Scheduler.GlobalStatus.IsInteractiveMode || !(objProperties is string))
				{
					TraceMessage.WriteAlways(ToString(), "Calling Registry.RunTest: " + Properties.TestName, TraceMessageType.Trace);
					Root.Scheduler.Registry.RunTest(this, ref objParameters, ref objProperties);
				}
			}
			else
			{
				WriteOutParameterValuesToTrace(objParameters, Properties.TestName);
				RuntimeAttributes.TestRan = true;
				RuntimeAttributes.TestStartTime = DateTime.Now;
				if (this is HiveTest)
				{
					MsgData msgData2 = CreateRunMsgData();
					((QTMRegistry)Root.Scheduler.QTMData.theRegistry).SetGlobalVariable("CurrentTestDetails", msgData2);
					((QTMRegistry)Root.Scheduler.QTMData.theRegistry).RunTest(this, ref objParameters, ref objProperties);
				}
				else
				{
					SimulationData simulationData = new SimulationData();
					TimerCallback callback = TimerDone;
					System.Threading.Timer timer = new System.Threading.Timer(callback, simulationData, 300, 1000);
					simulationData.timer = timer;
					simulationData.Test = this;
				}
			}
			string key = Properties.TestName;
			if (Properties.DescriptionName.Trim() != "")
			{
				key = Properties.DescriptionName.Trim();
			}
			Root.Scheduler.ListOfTestsRunning.Add(key, this);
			TestMessage tMessage = default(TestMessage);
			tMessage.ErrorCode = Properties.TestName;
			tMessage.Message = TestPath;
			tMessage.NodeRID = Properties.NodeRID;
			tMessage.Object = RuntimeAttributes.TestStartTime;
			tMessage.Result = TestResult.Passed;
			tMessage.TestIndex = Index;
			tMessage.TestPathInTree = TestPath;
			string gvValue = "";
			Root.Scheduler.Env.GlobalVariable.GetGlobalVariable("SN", out gvValue);
			tMessage.SerialNumber = gvValue;
			if (Parent is TestCaseTest)
			{
				tMessage.DoNotSendToPlugins = false;
			}
			tMessage.TestStartTime = RuntimeAttributes.TestStartTime;
			SetTestStartAndStopTimes(ref tMessage);
			tMessage.TestCaseRefID = GetTestCaseRefID(this);
			msgDelegate(TestMsgType.OnTestStart, tMessage);
			Root.Scheduler.mutTest.ReleaseMutex();
		}
		catch (TargetNotFoundException ex)
		{
			TraceMessage.WriteAlways(ToString(), "EXCEPTION: BaseTest.RunTest(" + testName + ") " + ex.ToString(), TraceMessageType.Trace);
			Root.Scheduler.mutTest.ReleaseMutex();
			ExceptionHandle(ex.Message);
		}
		catch (Exception ex2)
		{
			TraceMessage.WriteAlways(ToString(), "EXCEPTION: BaseTest.RunTest(" + testName + ") " + ex2.ToString(), TraceMessageType.Trace);
			AppMessageDialog.Show("Error Starting Test. Error: " + ex2.Message, "QSPR - Message Center", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1, MessageBoxOptions.ServiceNotification, DialogResult.OK, MessageDialogType.Exception);
			Root.Scheduler.mutTest.ReleaseMutex();
			ExceptionHandle(ex2.Message);
		}
		TraceMessage.WriteAlways(ToString(), "EXIT: BaseTest.RunTest(" + testName + ")", TraceMessageType.Trace);
	}

	public virtual void UpdateLoopIterations()
	{
		try
		{
			if (!RuntimeAttributes.CurrentLoopIteration.HasValue && !string.IsNullOrWhiteSpace(Root.Scheduler.GlobalStatus.LoopDetails))
			{
				RuntimeAttributes.CurrentLoopIteration = 1;
				int result = 1;
				if (Properties.Scenarios != null)
				{
					LoopCondition loopCondition = (LoopCondition)Properties.Scenarios.LoopConditions[0];
					if (loopCondition.LoopType != QC.QsprTestObjects.Loops.LoopTypes.BYCOUNT)
					{
						result = ((loopCondition.LoopType == QC.QsprTestObjects.Loops.LoopTypes.BYTIME) ? 1 : ((LoopCondition)Properties.Scenarios.LoopConditions[0]).LoopValues.Count);
					}
					else if (!int.TryParse(((LoopCondition)Properties.Scenarios.LoopConditions[0]).LoopValuesAsString, out result))
					{
						result = 1;
					}
				}
				RuntimeAttributes.MaxLoopIteration = Parent.RuntimeAttributes.MaxLoopIteration * result;
			}
			else
			{
				RuntimeAttributes.CurrentLoopIteration++;
			}
		}
		catch (Exception ex)
		{
			TraceMessage.Write("FolderTest.UpdateLoopIterations()", "Failed to update loop iterations, exception: " + ex.ToString(), TraceMessageType.Exception);
		}
	}

	private MsgData CreateRunMsgData()
	{
		MsgData result = default(MsgData);
		result.TestFullPath = Properties.TestName;
		if (this is HiveTest)
		{
			result.ParamResult = new ArrayList();
		}
		else
		{
			result.ParamResult = Properties.Parameters.GetParameterExportList(onlyLoggedParameters: false, outputOnly: false, ignoreEmptyStringValues: false);
		}
		result.ErrorCode = Properties.TestErrorCode;
		result.LoggingEnabled = Properties.LoggingEnabled;
		result.LoopDetails = Root.Scheduler.GlobalStatus.LoopDetails;
		result.TestName = Properties.TestName;
		result.TestPathInTree = TestPath;
		if (IsTestStep)
		{
			result.TestCaseInfo.TestCaseRefID = GetTestCaseRefID(this);
		}
		return result;
	}

	internal long GetTestCaseRefID(BaseTest test)
	{
		_ = string.Empty;
		if (test.Parent == null)
		{
			return -1L;
		}
		if (test.Parent is TestCaseTest)
		{
			TestCaseTest testCaseTest = (TestCaseTest)test.Parent;
			TestCaseTestProperties testCaseTestProperties = (TestCaseTestProperties)testCaseTest.Properties;
			return testCaseTestProperties.TestCaseID;
		}
		return GetTestCaseRefID(test.Parent);
	}

	private void WriteOutParameterValuesToTrace(object objParameters, string testName)
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.AppendLine($"Test {testName} is running in simulation mode.");
		if (objParameters == null)
		{
			return;
		}
		for (int i = 0; i < ((object[,])objParameters).GetLength(0); i++)
		{
			try
			{
				string arg = ((object[,])objParameters)[i, 0].ToString();
				string text = ((object[,])objParameters)[i, 1].ToString();
				stringBuilder.AppendLine(string.Format("{0}, Value: {1}", arg, string.IsNullOrEmpty(text) ? "" : text));
			}
			catch
			{
			}
		}
		Root.Scheduler.TestMsgBroadCaster.OnTextOut("Trace", stringBuilder.ToString());
	}

	protected void ExceptionHandle(string message)
	{
		Root.Scheduler.GlobalStatus.Abort = true;
		ArrayList arrayList = new ArrayList();
		MsgData msgData = default(MsgData);
		msgData.msgType = TestMsgType.OnAbort;
		msgData.TestFullPath = TestPath;
		msgData.TestIndex = Index;
		arrayList.Add(msgData);
		TestMessage message2 = default(TestMessage);
		message2.Message = TestPath;
		message2.NodeRID = Properties.NodeRID;
		message2.Object = arrayList;
		message2.Result = TestResult.Exception;
		message2.TestIndex = Index;
		message2.Duration = DateTime.Now - RuntimeAttributes.TestStartTime;
		msgDelegate(TestMsgType.OnAbort, message2);
		Properties.DescriptionName = "";
	}

	public void TimerDone(object state)
	{
		SimulationData simulationData = null;
		try
		{
			simulationData = (SimulationData)state;
			simulationData.timer.Dispose();
			simulationData.timer = null;
		}
		catch
		{
		}
		finally
		{
			if (simulationData != null)
			{
				string testName = simulationData.Test.Properties.TestName;
				if (simulationData.Test.Properties.DescriptionName.Trim() != "")
				{
					testName = simulationData.Test.Properties.DescriptionName.Trim();
				}
				Root.Scheduler.TestMsgBroadCaster.OnTestDone(testName, int.MaxValue, simulationData.Test.Properties.Parameters);
			}
		}
	}

	public virtual void GetSelectedTests(ref ArrayList testNames, ref ArrayList nodeNames)
	{
		if (Properties.CheckStateTest != 0)
		{
			testNames.Add(Properties.TestName);
			nodeNames.Add(Properties.RealName);
		}
	}

	public virtual void GetSelectedTestCasesCount(ref int count)
	{
		if (Properties.CheckStateTest != 0 && this is TestCaseTest)
		{
			count++;
		}
	}

	public virtual void GetSelectedTestCount(ref int count)
	{
		if (Properties.CheckStateTest != 0 && this is DotNetTest)
		{
			count++;
		}
	}

	internal void SetTestStartAndStopTimes(ref TestMessage tMessage)
	{
		TraceMessage.Write(ToString(), "ENTER: BaseTest.SetTestStartAndStopTimes()", TraceMessageType.Trace);
		if (Root.Scheduler.Env.GlobalVariable.GetGlobalVariableObject("CurrentTestDetails", out var gvValue) && gvValue is MsgData msgData)
		{
			if (msgData.TestStartTime.HasValue)
			{
				tMessage.TestStartTime = msgData.TestStartTime;
				runtimeAttributes.TestStartTime = msgData.TestStartTime.Value;
			}
			if (msgData.TestStopTime.HasValue)
			{
				tMessage.TestStopTime = msgData.TestStopTime;
				runtimeAttributes.TestStopTime = msgData.TestStopTime.Value;
			}
			else if (tMessage.TestStopTime.HasValue)
			{
				runtimeAttributes.TestStopTime = tMessage.TestStopTime.Value;
			}
		}
		TraceMessage.Write(ToString(), "EXIT: BaseTest.SetTestStartAndStopTimes()", TraceMessageType.Trace);
	}

	internal object GetDynamicOutputParametersObjectArray()
	{
		try
		{
			try
			{
				ArrayList additionalOutputParamaters = Root.Scheduler.Env.QTMInfo.GetAdditionalOutputParamaters();
				Hashtable hashtable = new Hashtable();
				if (additionalOutputParamaters.Count > 0)
				{
					foreach (ParamValue item in additionalOutputParamaters)
					{
						TestParameter testParameterFromParamValue = GetTestParameterFromParamValue(item);
						hashtable.Add(testParameterFromParamValue.Name, testParameterFromParamValue);
					}
				}
				return ParameterHandler.GetParameterObject(hashtable);
			}
			catch
			{
			}
		}
		catch
		{
		}
		return null;
	}

	private TestParameter GetTestParameterFromParamValue(ParamValue p)
	{
		TestParameter testParameter = new TestParameter();
		testParameter.Name = p.ParamName;
		testParameter.DataType = "String";
		testParameter.NumberOfElements = p.NumElements;
		if (p.Value != null && p.Value.Count > 0)
		{
			testParameter.Value = string.Join(",", from o in p.Value.ToArray()
				select o.ToString());
		}
		if (p.DataTableValue != null)
		{
			testParameter.DataTableValue = p.DataTableValue;
		}
		testParameter.IOType = p.IOType.ToString();
		if (p.UL != null && p.UL.Count > 0)
		{
			testParameter.UpperLimit = p.UL[0].ToString();
		}
		if (p.LL != null && p.LL.Count > 0)
		{
			testParameter.LowerLimit = p.LL[0].ToString();
		}
		testParameter.UnitOfMeasure = ((p.Unit == null) ? string.Empty : p.Unit);
		testParameter.Description = ((p.Desc == null) ? string.Empty : p.Desc);
		testParameter.Constraints = ((p.Constraint == null) ? string.Empty : p.Constraint);
		testParameter.DisplayHint = (QC.QTMDotNetKernelInterface.DisplayHints)p.DispHint;
		testParameter.CheckedState = CheckState.Checked;
		testParameter.IsNullable = false;
		testParameter.ParentName = ((p.ParentName == null) ? string.Empty : p.ParentName);
		testParameter.IsArray = p.Value.Count > 1;
		testParameter.NumberOfElements = p.Value.Count;
		testParameter.IsEditableInTestPlan = false;
		return testParameter;
	}

	public void UpdateDynamicLimits(BaseTest test)
	{
		try
		{
			if (Root.ReportGenerator == null)
			{
				return;
			}
			string gvValue = string.Empty;
			if (!Root.Scheduler.Env.GlobalVariable.GetGlobalVariable("LIMIT_GROUP", out gvValue))
			{
				return;
			}
			ReportGenerator reportGenerator = Root.ReportGenerator;
			List<LimitGroupType> allLimitDescriptorGroupType = reportGenerator.GetAllLimitDescriptorGroupType();
			string empty = string.Empty;
			for (int i = 0; i < allLimitDescriptorGroupType.Count; i++)
			{
				if (allLimitDescriptorGroupType[i].Name == gvValue)
				{
					empty = allLimitDescriptorGroupType[i].Index;
					break;
				}
			}
			if (string.IsNullOrWhiteSpace(empty))
			{
				return;
			}
			string testName = test.Properties.TestName;
			if (test.TestCase != null)
			{
				testName = test.TestCase.Properties.TestName;
			}
			GetInputParamInfoFromTestParameters(test, out var inputParamInfos, out var outputParamNames);
			AddGlobalVariablesToInputParamInfos(inputParamInfos);
			Dictionary<string, Tuple<double, double>> customLimits = reportGenerator.GetCustomLimits(testName, inputParamInfos, outputParamNames, empty);
			foreach (string key in customLimits.Keys)
			{
				ParameterCls parameter = test.Properties.Parameters.GetParameter(key);
				parameter.LowerLimit = (double.IsNaN(customLimits[key].Item1) ? "" : customLimits[key].Item1.ToString());
				parameter.UpperLimit = (double.IsNaN(customLimits[key].Item2) ? "" : customLimits[key].Item2.ToString());
			}
			UpdateArrayLimits(reportGenerator, empty, test, testName, inputParamInfos, outputParamNames);
		}
		catch (Exception ex)
		{
			AppMessageDialog.Show("An error occured updating dynamic limits for test: " + test.Properties.TestName + "\n" + ex.ToString(), "Error in Dynamic Limits", DialogResult.OK, MessageDialogType.Error);
		}
	}

	private void UpdateArrayLimits(ReportGenerator reportGenerator, string limitGroupIndex, BaseTest test, string testName, Dictionary<string, QC.CTDS.DM.DataStructures.InputDataStructure.ParamInfo> inputParamInfos, List<string> outputParamNames)
	{
		foreach (ParameterCls parameter in test.Properties.Parameters)
		{
			if (parameter.Type != IOType.Output || parameter.NoOfElements <= 1)
			{
				continue;
			}
			StringBuilder stringBuilder = new StringBuilder();
			StringBuilder stringBuilder2 = new StringBuilder();
			for (int i = 0; i < parameter.NoOfElements; i++)
			{
				QC.CTDS.DM.DataStructures.InputDataStructure.ParamInfo paramInfo = new QC.CTDS.DM.DataStructures.InputDataStructure.ParamInfo();
				paramInfo.StrVal = i.ToString();
				paramInfo.Val = i;
				QC.CTDS.DM.DataStructures.InputDataStructure.ParamInfo value = paramInfo;
				if (inputParamInfos.ContainsKey(".ARRAY_INDEX"))
				{
					inputParamInfos[".ARRAY_INDEX"] = value;
				}
				else
				{
					inputParamInfos.Add(".ARRAY_INDEX", value);
				}
				Dictionary<string, Tuple<double, double>> customLimits = reportGenerator.GetCustomLimits(testName, inputParamInfos, outputParamNames, limitGroupIndex);
				Tuple<double, double> tuple = ((!customLimits.ContainsKey(parameter.Name)) ? new Tuple<double, double>(double.NaN, double.NaN) : customLimits[parameter.Name]);
				if (i == 0)
				{
					stringBuilder.Append(double.IsNaN(tuple.Item1) ? "" : tuple.Item1.ToString());
					stringBuilder2.Append(double.IsNaN(tuple.Item2) ? "" : tuple.Item2.ToString());
				}
				else
				{
					stringBuilder.Append("," + (double.IsNaN(tuple.Item1) ? "" : tuple.Item1.ToString()));
					stringBuilder2.Append("," + (double.IsNaN(tuple.Item2) ? "" : tuple.Item2.ToString()));
				}
			}
			parameter.LowerLimit = stringBuilder.ToString();
			parameter.UpperLimit = stringBuilder2.ToString();
		}
	}

	private void GetInputParamInfoFromTestParameters(BaseTest test, out Dictionary<string, QC.CTDS.DM.DataStructures.InputDataStructure.ParamInfo> inputParamInfos, out List<string> outputParamNames)
	{
		inputParamInfos = new Dictionary<string, QC.CTDS.DM.DataStructures.InputDataStructure.ParamInfo>(StringComparer.Ordinal);
		outputParamNames = new List<string>();
		foreach (ParameterCls parameter in test.Properties.Parameters)
		{
			ParameterCls.GetIsArray(parameter, test is DotNetTest, test.RealName, "");
			if (parameter.Type == IOType.Input)
			{
				QC.CTDS.DM.DataStructures.InputDataStructure.ParamInfo paramInfo = new QC.CTDS.DM.DataStructures.InputDataStructure.ParamInfo();
				paramInfo.StrVal = parameter.Value;
				paramInfo.ParamUnit = parameter.Unit;
				QC.CTDS.DM.DataStructures.InputDataStructure.ParamInfo paramInfo2 = paramInfo;
				if (double.TryParse(parameter.Value, out var result))
				{
					paramInfo2.Val = result;
				}
				inputParamInfos.Add(parameter.Name, paramInfo2);
			}
			else if (parameter.Type == IOType.Output)
			{
				outputParamNames.Add(parameter.Name);
			}
		}
	}

	private void AddGlobalVariablesToInputParamInfos(Dictionary<string, QC.CTDS.DM.DataStructures.InputDataStructure.ParamInfo> inputParamInfos)
	{
		foreach (object key in Root.Scheduler.Env.GlobalVariable.GVariables.Keys)
		{
			if (!inputParamInfos.ContainsKey(key.ToString()))
			{
				Root.Scheduler.Env.GlobalVariable.GetGlobalVariable(key.ToString(), out var gvValue);
				double.TryParse(gvValue, out var result);
				inputParamInfos.Add(key.ToString(), new QC.CTDS.DM.DataStructures.InputDataStructure.ParamInfo
				{
					StrVal = gvValue,
					Val = result
				});
			}
		}
	}

	public virtual bool IsValidTestCase()
	{
		return true;
	}

	public FolderTest FindLoopParent(string parentIndex)
	{
		TraceMessage.Write(ToString(), "FindLoopParent", TraceMessageType.Trace);
		try
		{
			if (Parent != null)
			{
				if (Parent.Index == parentIndex)
				{
					return Parent;
				}
				return Parent.FindLoopParent(parentIndex);
			}
			return null;
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "FindLoopParent " + ex.Message, TraceMessageType.Exception);
			return null;
		}
	}

	public virtual void CreateParent(FolderTest pTest)
	{
		TraceMessage.Write(ToString(), "CreateParent", TraceMessageType.Trace);
		try
		{
			Parent = pTest;
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "CreateParent " + ex.Message, TraceMessageType.Exception);
		}
	}

	public void CreateLoopParentList(ArrayList dList)
	{
		TraceMessage.Write(ToString(), "CheckLoopParents", TraceMessageType.Trace);
		try
		{
			if (this is FolderTest)
			{
				foreach (BaseTest test in ((FolderTest)this).TestList)
				{
					test.CreateLoopParentList(dList);
				}
				return;
			}
			foreach (string loopLink in Properties.LoopLinks)
			{
				FolderTest folderTest = FindLoopParent(loopLink);
				if (folderTest == null)
				{
					DeletedLink deletedLink = default(DeletedLink);
					deletedLink.ParentIndex = loopLink;
					deletedLink.ChildIndex = Index;
					if (!dList.Contains(deletedLink))
					{
						dList.Add(deletedLink);
					}
				}
			}
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "CheckLoopParents " + ex.Message, TraceMessageType.Exception);
		}
	}

	public virtual void RemoveLoopLinkTest(string strIndex)
	{
		try
		{
			Properties.RemoveLoopLink(strIndex);
		}
		catch (Exception ex)
		{
			TraceMessage.Write(ToString(), "RemoveLoopLinkTest " + ex.Message, TraceMessageType.Exception);
		}
	}

	public TestCaseTest GetParentTestCase()
	{
		if (parent == null)
		{
			return null;
		}
		if (parent is TestCaseTest)
		{
			return parent as TestCaseTest;
		}
		if (parent.GetType() == typeof(FolderTest))
		{
			return parent.GetParentTestCase();
		}
		return null;
	}

	private string GetTestPath(bool uniquePath, bool includeIndex = true)
	{
		string text = (uniquePath ? "|" : ".");
		if (this is RootTest)
		{
			if (uniquePath && includeIndex)
			{
				return "0" + text + Properties.TestName;
			}
			return Properties.TestName;
		}
		if (includeIndex)
		{
			int num = -1;
			if (parent != null)
			{
				num = parent.TestList.IndexOf(this);
			}
			if (uniquePath)
			{
				return GetFolderPath(uniquePath, includeIndex) + text + num + text + Properties.TestName;
			}
			return GetFolderPath(uniquePath, includeIndex) + text + Properties.TestName + text + num;
		}
		return GetFolderPath(uniquePath, includeIndex) + text + Properties.TestName;
	}

	private string GetFolderPath(bool uniquePath, bool includeIndex = true)
	{
		string text = (uniquePath ? "|" : ".");
		string text2 = "";
		if (parent != null)
		{
			FolderTest folderTest = parent;
			while (!(folderTest is RootTest) && folderTest.parent != null)
			{
				if (includeIndex)
				{
					if (uniquePath)
					{
						int num = folderTest.parent.TestList.IndexOf(folderTest);
						text2 = text + num + text + folderTest.Properties.TestName + text2;
					}
					else
					{
						text2 = text + folderTest.Properties.TestName + text2;
					}
				}
				else
				{
					text2 = text + folderTest.Properties.TestName + text2;
				}
				folderTest = folderTest.parent;
			}
		}
		RootTest rootTest = GetRootTest();
		if (rootTest != null)
		{
			if (includeIndex)
			{
				if (uniquePath)
				{
					return "0" + text + rootTest.Properties.TestName + text2;
				}
				return rootTest.Properties.TestName + text2;
			}
			return rootTest.Properties.TestName + text2;
		}
		return text2;
	}

	protected virtual void RaisePropertyChanged(string propertyName)
	{
		if (this.PropertyChanged != null)
		{
			this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
		}
	}
}
