alielie
2026-09-10 f3889f2d36c50cf99468594854def9b7ed069fb5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
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<TestStepList> seqs)
                    {
                        foreach (var seq in seqs)
                        {
                            seq.Parent = plan;
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
            return plan;
        }
    }
}