using System; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Xml; using System.Xml.Linq; using static OpenTap.TestPlan; namespace OpenTap.Addin.Reader { public class TestPlanReader { internal static readonly OpenTap.TraceSource Log = OpenTap.Log.CreateSource(nameof(TestPlanReader)); const string TestPlanRootName = "TestPlan"; const string SequencesName = "Sequences"; public static TestPlan ReadTestPlan(string filePath) { if (filePath == null) throw new ArgumentNullException(nameof(filePath)); var timer = Stopwatch.StartNew(); // Open document using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { var loadedPlan = ReadTestPlanFromStream(fs, filePath); Log.Info(timer, "Read test plan from {0}", filePath); return loadedPlan; } } public static TestPlan ReadTestPlanFromStream(Stream stream, string path, bool IgnoreLoadErrors = false) { if (stream == null) throw new ArgumentNullException(nameof(stream)); var document = XDocument.Load(stream, LoadOptions.SetLineInfo); return ReadTestPlanFromDocument(document, path, IgnoreLoadErrors); } public static TestPlan ReadTestPlanFromDocument(XDocument document, string path, bool IgnoreLoadErrors = false) { var root = document.Elements().First(); string rootName = XmlConvert.DecodeName(root.Name.LocalName); if (rootName != TestPlanRootName) { throw new PlanLoadException("Error File."); } TestPlan plan = new TestPlan(path); var props = PropertyInfoCache.GetProps(typeof(TestPlan)); void PostAction(object obj) { if (obj is TestStep step) { step.Root = plan; return; } } foreach (var element in root.Elements()) { try { string name = XmlConvert.DecodeName(element.Name.LocalName); if (!props.ContainsKey(name)) { continue; } var value = DefaultObjectReader.ReadObject(props[name].PropertyType, element, PostAction); props[name].SetValue(plan, value); if (name == SequencesName && value is ObservableCollection seqs) { foreach (var seq in seqs) { seq.Parent = plan; } } } catch (Exception ex) { throw ex; } } return plan; } } }