using System; using System.IO; using System.Linq; using System.Text; using NUnit.Framework; using OpenTap.Engine.UnitTests; namespace OpenTap.UnitTests { public class ComponentSettingsTest { [Test] public void TestCacheInvalidated() { using (Session.Create()) { EngineSettings.Current.OperatorName = "TEST"; Assert.AreEqual("TEST", EngineSettings.Current.OperatorName); int callCount = 0; EngineSettings.Current.CacheInvalidated += (s, e) => { Assert.IsTrue(s is EngineSettings); callCount += 1; }; EngineSettings.Current.Invalidate(); Assert.AreEqual(1, callCount); Assert.AreNotEqual("TEST", EngineSettings.Current.OperatorName); EngineSettings.Current.OperatorName = "TEST"; // The event must be re-configured when the cache is invalidated. EngineSettings.Current.CacheInvalidated += (s, e) => { Assert.IsTrue(s is EngineSettings); callCount += 1; }; ComponentSettings.InvalidateAllSettings(); Assert.AreEqual(2, callCount); } Assert.AreNotEqual("TEST", EngineSettings.Current.OperatorName); } [Test] public void TestSetCurrentComponentSettings() { var initialEngineSettings = EngineSettings.Current; try { string operatorName = "John"; EngineSettings engineSettings = new EngineSettings(); engineSettings.OperatorName = operatorName; using (MemoryStream memoryStream = new MemoryStream()) { using (var xmlWriter = System.Xml.XmlWriter.Create(memoryStream, new System.Xml.XmlWriterSettings { Indent = true })) { var serializer = new TapSerializer(); serializer.Serialize(xmlWriter, engineSettings); } ComponentSettings.SetCurrent(memoryStream); } Assert.AreEqual(operatorName, EngineSettings.Current.OperatorName); } finally { using (MemoryStream memoryStream = new MemoryStream()) { using (var xmlWriter = System.Xml.XmlWriter.Create(memoryStream, new System.Xml.XmlWriterSettings { Indent = true })) { var serializer = new TapSerializer(); serializer.Serialize(xmlWriter, initialEngineSettings); } ComponentSettings.SetCurrent(memoryStream); } } } [Test] public void TestInvalidSetCurrentSettings() { string content = "Definitely not ComponentSettingsXML"; try { using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(content))) ComponentSettings.SetCurrent(memoryStream); Assert.Fail("This should not pass"); } catch (Exception ex) { Assert.IsTrue(ex.Message.Contains(content)); } } [Test] public void TestErrorsSetFromStream() { { // Two missing dependency errors string content = @" "; using var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(content)); ComponentSettings.SetCurrent(memoryStream, out var errors); Assert.AreEqual(2, errors.Count()); CollectionAssert.Contains(errors.Select(e => e.Message), "Package 'Not Installed Plugin' is required to load, but it is not installed."); CollectionAssert.Contains(errors.Select(e => e.Message), "Package 'Also Not Installed Plugin' is required to load, but it is not installed."); } { // No xml errors var content = @" "; using var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(content)); ComponentSettings.SetCurrent(memoryStream, out var errors); Assert.AreEqual(0, errors.Count()); } { // Invalid component setting -- missing type string content = @" "; using var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(content)); ComponentSettings.SetCurrent(memoryStream, out var errors); Assert.AreEqual(1, errors.Count()); var err = errors.First().ToString(); StringAssert.Contains("Stream does not contain valid ComponentSettings. Unable to determine ComponentSettings type from root attribute", err); } { // Invalid data var content = "Definitely not ComponentSettingsXML"; using var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(content)); ComponentSettings.SetCurrent(memoryStream, out var errors); Assert.AreEqual(1, errors.Count()); StringAssert.Contains("Data at the root level is invalid. Line 1, position 1.", errors.First().Message); } } [Display("Test Settings", Groups: new []{"Test Settings", "With Groups"})] public class TestSettingsWithGroups : ComponentSettings { public int Value { get; set; } } [Test] public void TestSaveSettingsWithGroup() { var s = ComponentSettings.Current; s.Value = 0; Assert.AreEqual(0, s.Value); s.Save(); var newValue = 123; s.Value = newValue; Assert.AreEqual(newValue, s.Value); s.Save(); s.Reload(); s.Invalidate(); s = ComponentSettings.Current; Assert.AreEqual(newValue, s.Value); } public class ThrowingSetting : ComponentSettings { public static bool Throw { get; set; } = false; public ThrowingSetting() { if (Throw) throw new Exception("Some exception"); } } [Test] public void TestSessionCreateDoesNotThrow() { try { ComponentSettings.InvalidateAllSettings(); ThrowingSetting.Throw = true; Assert.That(ThrowingSetting.Current, Is.Null); using (Session.Create(SessionOptions.None)) Assert.That(ThrowingSetting.Current, Is.Null); using (Session.Create(SessionOptions.OverlayComponentSettings)) Assert.That(ThrowingSetting.Current, Is.Null); } finally { ThrowingSetting.Throw = false; } } [Test] public void TestSessionCreateDoesNotOverlayIncorrectInstance() { ComponentSettings.InvalidateAllSettings(); ThrowingSetting.Throw = false; // The first instance can be correctly constructed Assert.That(ThrowingSetting.Current, Is.Not.Null); // Make future constructors throw try { ThrowingSetting.Throw = true; // With no overlay settings, the first instance is returned using (Session.Create(SessionOptions.None)) Assert.That(ThrowingSetting.Current, Is.Not.Null); // With overlay settings, we cannot create a new instance using (Session.Create(SessionOptions.OverlayComponentSettings)) Assert.That(ThrowingSetting.Current, Is.Null); // The original instance is still used using (Session.Create(SessionOptions.None)) Assert.That(ThrowingSetting.Current, Is.Not.Null); } finally { ThrowingSetting.Throw = false; } } [Test] public void TestPersistenceOfSaveAll() { var instrumentSettingsSavePath = ComponentSettings.GetSaveFilePath(typeof(InstrumentSettings)); if (File.Exists(instrumentSettingsSavePath)) File.Delete(instrumentSettingsSavePath); var initialInstrumentSettings = InstrumentSettings.Current; try { InstrumentSettings instruments = new InstrumentSettings(); instruments.Add(new ScpiDummyInstrument()); using (MemoryStream memoryStream = new MemoryStream()) { using (var xmlWriter = System.Xml.XmlWriter.Create(memoryStream, new System.Xml.XmlWriterSettings { Indent = true })) { var serializer = new TapSerializer(); serializer.Serialize(xmlWriter, instruments); } ComponentSettings.SetCurrent(memoryStream); } ComponentSettings.SaveAllCurrentSettings(); // Instument has been added and SaveAllCurrentSettings is called Assert.IsTrue(File.Exists(instrumentSettingsSavePath)); // This FAILS! } finally { using (MemoryStream memoryStream = new MemoryStream()) { using (var xmlWriter = System.Xml.XmlWriter.Create(memoryStream, new System.Xml.XmlWriterSettings { Indent = true })) { var serializer = new TapSerializer(); serializer.Serialize(xmlWriter, initialInstrumentSettings); } ComponentSettings.SetCurrent(memoryStream); } } } } }