using System; using System.Collections.Generic; using System.IO; using System.Linq; using NUnit.Framework; using OpenTap.EngineUnitTestUtils; using OpenTap.Plugins.BasicSteps; namespace OpenTap.UnitTests { [TestFixture] public class ElementFactoryTest { public class ClassWithComplexList { public class ComplexElement { readonly ClassWithComplexList Parent; internal ComplexElement(ClassWithComplexList parent) { this.Parent = parent; } } public class ComplexList : List { readonly ClassWithComplexList parent; public ComplexList(ClassWithComplexList lst) { this.parent = lst; } } public class ComplexList2 : List { readonly ClassWithComplexList parent; public ComplexList2(ClassWithComplexList lst) { this.parent = lst; } } [ElementFactory(nameof(NewElement))] public List Items { get; set; } = new List(); [ElementFactory(nameof(NewElement))] [Factory(nameof(NewComplexList))] public ComplexList Items2 { get; set; } [Factory(nameof(NewComplexList))] public ComplexList Items3 { get; set; } // Complex list, simple elements [Factory(nameof(NewComplexList2))] public ComplexList2 Items4 { get; set; } [Factory(nameof(NewComplexList))] [ElementFactory(nameof(NewElement))] public ComplexList Items5 { get; set; } internal ComplexElement NewElement() { return new ComplexElement(this); } internal ComplexList NewComplexList() { return new ComplexList(this); } internal ComplexList2 NewComplexList2() { return new ComplexList2(this); } public ClassWithComplexList() { Items2 = new ComplexList(this); Items5 = new ComplexList(this); } } [Test] public void SerializeWithElementFactory() { var test = new ClassWithComplexList(); test.Items.Add(test.NewElement()); test.Items2.Add(test.NewElement()); test.Items5.Add(test.NewElement()); test.Items4 = test.NewComplexList2(); test.Items4.Add(10); var xml = new TapSerializer().SerializeToString(test); var test2 =(ClassWithComplexList) new TapSerializer(){IgnoreErrors = false}.DeserializeFromString(xml); Assert.AreEqual(1, test2.Items2.Count); Assert.IsNotNull(test2.Items2[0]); Assert.AreEqual(1, test2.Items.Count); Assert.IsNotNull(test2.Items[0]); Assert.IsNotNull(test2.Items5); Assert.AreEqual(1, test2.Items5.Count); Assert.AreEqual(10, test2.Items4[0]); } [Test] public void AnnotateWithElementFactory() { var test = new ClassWithComplexList(); var a = AnnotationCollection.Annotate(test); var complexItems = a.GetMember(nameof(test.Items2)); var collection = complexItems.Get(); collection.AnnotatedElements = collection.AnnotatedElements.Append(collection.NewElement()); int preCount = test.Items2.Count; a.Write(); int postCount = test.Items2.Count; Assert.AreEqual(0, preCount); Assert.AreEqual(1, postCount); } [Test] public void TestDeserializeParameterizedElements([Values(0, 1, 2, 3, 10)] int numRows) { using var s = Session.Create(SessionOptions.OverlayComponentSettings); var trace = new TestTraceListener(); Log.AddListener(trace); var plan = new TestPlan(); var sweep = new SweepParameterStep(); var delay = new DelayStep(); sweep.ChildTestSteps.Add(delay); plan.ChildTestSteps.Add(sweep); { /* parameterize DelaySecs */ var delaySecs = AnnotationCollection.Annotate(delay).GetMember(nameof(delay.DelaySecs)); var mem = delaySecs.Get().Member; mem.Parameterize(sweep, delay, $"Parameters \\ {mem.GetDisplayAttribute().Name}"); } { /* parameterize sweep values on test plan */ var sweepValues = AnnotationCollection.Annotate(sweep).GetMember(nameof(sweep.SweepValues)); var col = sweepValues.Get(); void addDelay(double delay) { var elem1 = col.NewElement(); var delayMem = elem1.GetMember("Parameters \\ Time Delay"); delayMem.Get().Value = delay; col.AnnotatedElements = col.AnnotatedElements.Append(elem1); } for (int i = 1; i <= numRows; i++) { addDelay(i); } sweepValues.Write(); sweepValues.Read(); var mem = sweepValues.Get().Member; mem.Parameterize(plan, sweep, $"Parameters \\ {mem.GetDisplayAttribute().Name}"); } TestPlan plan2 = null; { var ser = new TapSerializer() { IgnoreErrors = false }; var planXml = ser.SerializeToString(plan); Assert.That(ser.Errors, Is.Empty); plan2 = ser.DeserializeFromString(planXml) as TestPlan; Assert.That(ser.Errors, Is.Empty); } void AssertSweepsEqual(SweepRowCollection sweep1, SweepRowCollection sweep2) { Assert.That(sweep1.Count, Is.EqualTo(numRows)); Assert.That(sweep2.Count, Is.EqualTo(numRows)); for (int i = 0; i < sweep1.Count; i++) { var d1 = sweep1[i]; var d2 = sweep2[i]; foreach (var kvp in d1.Values) { var v1 = kvp.Value; var v2 = d2.Values[kvp.Key]; Assert.That(v1, Is.EqualTo(v2)); } } } { /* verify parameters were correctly deserialized */ var sweep1 = (SweepRowCollection)plan.ExternalParameters.Entries[0].Value; var sweep2 = (SweepRowCollection)plan2.ExternalParameters.Entries[0].Value; AssertSweepsEqual(sweep1, sweep2); } { var temp = Path.GetTempFileName(); TestPlanReference refStep; try { { /* test wrapping the test plan in a test plan reference step */ plan.Save(temp); var parentPlan = new TestPlan(); refStep = new TestPlanReference(); parentPlan.ChildTestSteps.Add(refStep); refStep.Filepath = new MacroString() { Text = temp }; refStep.LoadTestPlan(); var (parentPlan2, refStep2) = CloneRef(refStep); refStep2.LoadTestPlan(); { var sweep1 = GetSweepRow(refStep); var sweep2 = GetSweepRow(refStep2); AssertSweepsEqual(sweep1, sweep2); } refStep2.LoadTestPlan(); { var sweep1 = GetSweepRow(refStep); var sweep2 = GetSweepRow(refStep2); AssertSweepsEqual(sweep1, sweep2); } } { /* try adding new elements to the parameterized sweep and verify they are correctly serialized */ var a = AnnotationCollection.Annotate(refStep); var sweepValues = a.GetMember("Sweep Values"); var col = sweepValues.Get(); var elem1 = col.NewElement(); var delayMem = elem1.GetMember("Parameters \\ Time Delay"); delayMem.Get().Value = 123; col.AnnotatedElements = col.AnnotatedElements.Append(elem1); a.Write(); var (_, refStep2) = CloneRef(refStep); numRows += 1; { var sweep1 = GetSweepRow(refStep); var sweep2 = GetSweepRow(refStep2); AssertSweepsEqual(sweep1, sweep2); } /* ensure the sweep changes are not lost after reloading */ { refStep2.LoadTestPlan(); var sweep1 = GetSweepRow(refStep); var sweep2 = GetSweepRow(refStep2); AssertSweepsEqual(sweep1, sweep2); } } } finally { File.Delete(temp); } } { /* verify that there are no warnings or errors logged */ trace.Flush(); trace.WarningMessage.RemoveAll(warn => warn.StartsWith("Duplicate Test packages detected.", StringComparison.OrdinalIgnoreCase)); Assert.That(trace.WarningMessage, Is.Empty); Assert.That(trace.ErrorMessage, Is.Empty); } static (TestPlan, TestPlanReference) CloneRef(TestPlanReference refStep) { var parentPlan = new TestPlan(); parentPlan.ChildTestSteps.Add(refStep); var ser = new TapSerializer() { IgnoreErrors = false }; var xml = ser.SerializeToString(parentPlan); Assert.That(ser.Errors, Is.Empty); var plan2 = ser.DeserializeFromString(xml) as TestPlan; Assert.That(ser.Errors, Is.Empty); return (plan2, plan2.ChildTestSteps[0] as TestPlanReference); } static SweepRowCollection GetSweepRow(ITestStepParent p) => AnnotationCollection.Annotate(p).GetMember("Sweep Values").Get().Value as SweepRowCollection; } } }