// Copyright Keysight Technologies 2012-2019 // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, you can obtain one at http://mozilla.org/MPL/2.0/. using System; using System.ComponentModel; using NUnit.Framework; using System.IO; using System.Linq; namespace OpenTap.Engine.UnitTests { [TestFixture] public class UserCodeTest { [Test] public void ResultListeners() { resultListenerCrash[] crashers = new resultListenerCrash[]{ new resultListenerCrash{CrashResultPhase = resultListenerCrash.ResultPhase.PlanRunStart}, new resultListenerCrash{CrashResultPhase = resultListenerCrash.ResultPhase.StepRunStart}, new resultListenerCrash{CrashResultPhase = resultListenerCrash.ResultPhase.Result}, new resultListenerCrash{CrashResultPhase = resultListenerCrash.ResultPhase.StepRunCompleted}, new resultListenerCrash{CrashResultPhase = resultListenerCrash.ResultPhase.PlanRunCompleted}, new resultListenerCrash{CrashResultPhase = resultListenerCrash.ResultPhase.Open}, new resultListenerCrash{CrashResultPhase = resultListenerCrash.ResultPhase.Close} }; TestPlan testplan = new TestPlan(); testplan.Steps.Add(new TestStepTest()); foreach (var crasher in crashers) { testplan.Execute(new IResultListener[] { crasher }); } } [Test] [Ignore("Since the result thread is not synced with the test plan thread, the test plan might complete before the abort is used from the result listeners.")] public void ResultListenerAbortPlan() { // since the resultListenerCrash[] crashers = new resultListenerCrash[]{ new resultListenerCrash{CrashResultPhase = resultListenerCrash.ResultPhase.PlanRunStart, AbortPlan = true}, new resultListenerCrash{CrashResultPhase = resultListenerCrash.ResultPhase.StepRunStart, AbortPlan = true}, new resultListenerCrash{CrashResultPhase = resultListenerCrash.ResultPhase.Result, AbortPlan = true}, new resultListenerCrash{CrashResultPhase = resultListenerCrash.ResultPhase.StepRunCompleted, AbortPlan = true}, // The plan cannot be aborted on PlanRunCompleted. The at that point it will be ignored. new resultListenerCrash{CrashResultPhase = resultListenerCrash.ResultPhase.PlanRunCompleted, AbortPlan = true} }; TestPlan testplan = new TestPlan(); testplan.Steps.Add(new TestStepTest()); foreach (var c in crashers) { c.FinalVerdict = Verdict.NotSet; var expectedVerdict = Verdict.Aborted; if (c.CrashResultPhase != resultListenerCrash.ResultPhase.PlanRunStart) expectedVerdict = Verdict.Pass; // Simply running the plan. var planrun = testplan.Execute(new IResultListener[] { c }); Assert.AreEqual(expectedVerdict, planrun.Verdict); Assert.AreEqual(expectedVerdict, c.FinalVerdict); // Test that it works in composite runs. // Here it's important that the abort does not spill into the next run. // Which is why the plan is run twice. testplan.Open(new IResultListener[] { c }); c.FinalVerdict = Verdict.NotSet; Assert.AreEqual(expectedVerdict, testplan.Execute(new IResultListener[] { c }).Verdict); Assert.AreEqual(expectedVerdict, c.FinalVerdict); c.CrashResultPhase = resultListenerCrash.ResultPhase.None; c.FinalVerdict = Verdict.NotSet; Assert.AreEqual(Verdict.Pass, testplan.Execute(new IResultListener[] { c }).Verdict); Assert.AreEqual(Verdict.Pass, c.FinalVerdict); testplan.Close(); } } [Test] public void VersionProperties() { TestPlan tp = new TestPlan(); tp.ChildTestSteps.Add(new Plugins.BasicSteps.DelayStep()); var tpr = tp.Execute(); Assert.IsTrue(tpr.Parameters.Any(p => p.Group == "Version" && p.Name == "OpenTap"), "No engine version parameter found"); } [Test] public void InstrumentTestMethod() { InstrumentTest openCrash = new InstrumentTest { CrashPhase = InstrumentTest.InstrPhase.Open }; InstrumentTest closeCrash = new InstrumentTest { CrashPhase = InstrumentTest.InstrPhase.Close }; foreach (var instr in new IInstrument[] { openCrash, closeCrash }) { InstrumentTestStep step = new InstrumentTestStep { Instrument = instr }; TestPlan plan = new TestPlan(); plan.Steps.Add(step); plan.Execute(); } } [Test] public void DutInheritingFromIDut() { try { var dut = new InterfaceTestDut(); DutSettings setting = new DutSettings(); setting.Add(dut); } catch (Exception ex) { Assert.Fail("Unit test for duts inheriting from the IDut interface has trown an exception: " + ex.Message); } } [Test] public void ResultListenerInheritingFromIResultListener() { try { var resultListener = new InterfaceTestResultListenser(); var setting = new ResultSettings(); setting.Add(resultListener); } catch (Exception ex) { Assert.Fail("Unit test for result listener inheriting from the IResultListener interface has trown an exception: " + ex.Message); } } public void InstrumentInheritingFromIInstrument() { try { var instrument = new InterfaceTestInstrument(); var setting = new InstrumentSettings(); setting.Add(instrument); } catch (Exception ex) { Assert.Fail("Unit test for instruments inheriting from the IInstrument interface has trown an exception: " + ex.Message); } } } public class InstrumentTestStep : TestStep { public IInstrument Instrument { get; set; } public override void Run() { Assert.IsTrue(Instrument.IsConnected); } } public class InstrumentTest : Instrument { public InstrumentTest() { Name = "InstrTest"; } public enum InstrPhase { Open, Close } public InstrPhase CrashPhase { get; set; } public override void Open() { base.Open(); tryCrash(InstrPhase.Open); } public override void Close() { base.Close(); tryCrash(InstrPhase.Close); } void tryCrash(InstrPhase phase) { if (phase == CrashPhase) { throw new Exception("Intended Crash: " + phase.ToString()); } } } [DisplayName("Test\\Crash")] public class resultListenerCrash : ResultListener { public enum ResultPhase { PlanRunStart, PlanRunCompleted, StepRunStart, StepRunCompleted, Result, Close, Open, None } public bool AbortPlan { get; set; } public ResultPhase CrashResultPhase { get; set; } public Verdict FinalVerdict { get; set; } public resultListenerCrash() { Name = "CRSH"; CrashResultPhase = ResultPhase.PlanRunStart; } public override void Close() { base.Close(); if (CrashResultPhase == ResultPhase.Close) { throw new Exception("Intended Close Crash"); } } public override void Open() { base.Open(); if (CrashResultPhase == ResultPhase.Open) { throw new Exception("Intended Open Crash"); } } TestPlanRun planrun; public override void OnTestPlanRunStart(TestPlanRun planRun) { this.planrun = planRun; if (CrashResultPhase == ResultPhase.PlanRunStart) { if (AbortPlan) TapThread.Current.Abort(); else throw new Exception("Intended"); } } public override void OnTestPlanRunCompleted(TestPlanRun planRun, System.IO.Stream logStream) { FinalVerdict = planrun.Verdict; if (CrashResultPhase == ResultPhase.PlanRunCompleted) { if (AbortPlan) TapThread.Current.Abort(); else throw new Exception("Intended"); } planrun = null; } /// /// Called just before a test step is started. /// /// public override void OnTestStepRunStart(TestStepRun stepRun) { if (CrashResultPhase == ResultPhase.StepRunStart) { if (AbortPlan) TapThread.Current.Abort(); else throw new Exception("Intended"); } } public override void OnTestStepRunCompleted(TestStepRun stepRun) { if (CrashResultPhase == ResultPhase.StepRunCompleted) { if (AbortPlan) TapThread.Current.Abort(); else throw new Exception("Intended"); } } public override void OnResultPublished(Guid stepRunId, ResultTable result) { if (CrashResultPhase == ResultPhase.Result) { if (AbortPlan) TapThread.Current.Abort(); else throw new Exception("Intended"); } } } public class InterfaceTestDut : ValidatingObject, IDut { private bool isConnected = true; public bool IsConnected { get { return isConnected; } set { if (value == IsConnected) return; isConnected = value; OnPropertyChanged("IsConnected"); } } string _shortName = ""; public string Name { get { return _shortName; } set { if (_shortName != value) { _shortName = value; OnPropertyChanged("Name"); } } } public event EventHandler ActivityStateChanged; public void Close() { } public void Dispose() { } public void OnActivity() { if (ActivityStateChanged != null) { ActivityStateChanged.Invoke(this, new EventArgs()); } } public void Open() { } } public class InterfaceTestResultListenser : ValidatingObject, IResultListener { private bool isConnected = true; public bool IsConnected { get { return isConnected; } set { if (value == isConnected) return; isConnected = value; OnPropertyChanged("IsConnected"); } } string _shortName = "InterfaceTestResultListener"; public string Name { get { return _shortName; } set { if (_shortName != value) { _shortName = value; OnPropertyChanged("Name"); } } } public event EventHandler ActivityStateChanged; public void OnResultPublished(Guid stepRun, ResultTable result) { } public void Close() { } public void Dispose() { } public void OnActivity() { if (ActivityStateChanged != null) { ActivityStateChanged.Invoke(this, new EventArgs()); } } public void OnTestPlanRunCompleted(TestPlanRun planRun, Stream logStream) { } public void OnTestPlanRunStart(TestPlanRun planRun) { } public void OnTestStepRunCompleted(TestStepRun stepRun) { } public void OnTestStepRunStart(TestStepRun stepRun) { } public void Open() { } } [DisplayName("InterfaceTestInstrument")] public class InterfaceTestInstrument : IInstrument { private bool isConnected = false; public bool IsConnected { get { return isConnected; } set { if (value == isConnected) return; isConnected = value; OnPropertyChanged("IsConnected"); } } private void OnPropertyChanged(string v) { if (PropertyChanged != null) { PropertyChanged.Invoke(this, new PropertyChangedEventArgs(v)); } } string _shortName = "InterfaceTestInstrument"; public string Name { get { return _shortName; } set { if (_shortName != value) { _shortName = value; OnPropertyChanged("Name"); } } } public event EventHandler ActivityStateChanged; public event PropertyChangedEventHandler PropertyChanged; public void Close() { IsConnected = false; } public void Dispose() { } public void OnActivity() { if (ActivityStateChanged != null) { ActivityStateChanged.Invoke(this, new EventArgs()); } } public void Open() { IsConnected = true; } } public class QuickTestStep : TestStep { public InterfaceTestInstrument Instrument { get; set; } public override void Run() { } } }