using System; using System.Linq; using System.Threading; using Hylasoft.Opc.Common; using Hylasoft.Opc.Ua; using NUnit.Framework; using System.Configuration; using Opc.Ua.Client; using Opc.Ua; using System.Collections.Generic; using System.Threading.Tasks; namespace Hylasoft.Opc.Tests { [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1001:TypesThatOwnDisposableFieldsShouldBeDisposable", Justification = "Test Class"), TestFixture] public class UaTest { private UaClient _client; [SetUp] public void Init() { _client = new UaClient(new Uri(ConfigurationManager.AppSettings["UATestEndpoint"])); _client.Connect(); } [TearDown] public void Cleanup() { _client.Dispose(); } [Test] public void StatusTest() { Assert.AreEqual(OpcStatus.Connected, _client.Status); } [Test] public void ReadNodeTest() { var val = _client.Read<string>("Server.ServerStatus.BuildInfo.ManufacturerName"); Assert.AreEqual("OPC Foundation", val.Value); } [Test] public void WriteNodeTest() { const string tag = "Data.Static.Scalar.ByteValue"; _client.Write(tag, (byte)3); var val = _client.Read<byte>(tag); Assert.AreEqual(3, val.Value); _client.Write(tag, (byte)13); val = _client.Read<byte>(tag); Assert.AreEqual(13, val.Value); } [Test] public void ReadArrayNodeTest() { var val = _client.Read<bool[]>("Data.Static.Array.BooleanValue"); Assert.Greater(val.Value.Length, 0); } [Test] public void WriteArrayNodeTest() { const string tag = "Data.Static.Array.BooleanValue"; var val1 = new[] { true, false, false }; var val2 = new[] { false, false }; _client.Write(tag, val1); var val = _client.Read<bool[]>(tag); Assert.True(!val.Value.Zip(val1, (a, b) => a == b).Contains(false)); _client.Write(tag, val2); val = _client.Read<bool[]>(tag); Assert.True(!val.Value.Zip(val2, (a, b) => a == b).Contains(false)); } [Test] public void FailWriteTest() { // fails for wrong tag Assert.Throws<OpcException>(() => _client.Write("WRONG TAG", (byte)3)); // fails for wrong type Assert.Throws<OpcException>(() => _client.Write("Data.Static.Scalar.ByteValue", "WRONG TYPE")); // fails for not writing allowed Assert.Throws<OpcException>(() => _client.Write("Server.ServerStatus.BuildInfo.ManufacturerName", "READ ONLY")); } [Test] public void FailReadTest() { // fails for wrong tag Assert.Throws<OpcException>(() => _client.Read<int>("XXXXXX")); // fails for not readable tag Assert.AreEqual(Quality.Bad, _client.Read<string>("Server").Quality); } [Test] public void MonitorTest() { const string tag = "Data.Static.Scalar.ByteValue"; var executed = 0; _client.Monitor<byte>(tag, (val1, u) => { executed++; u(); }); _client.Monitor<byte>(tag, (val1, u) => { executed++; u(); }); _client.Monitor<byte>(tag, (val1, u) => { executed++; u(); }); const int interval = 100; Thread.Sleep(interval); _client.Write(tag, (byte)10); Thread.Sleep(interval); _client.Write(tag, (byte)11); Thread.Sleep(interval); _client.Write(tag, (byte)12); Thread.Sleep(interval); _client.Write(tag, (byte)13); Thread.Sleep(interval); Assert.AreEqual(3, executed); } [Test] public void UaTestExtension() { var client = new TestExtendUaClient(new Uri(ConfigurationManager.AppSettings["UATestEndpoint"])); client.Connect(); Assert.IsInstanceOf(typeof(Session), client.SessionExtended); } [Test] public void UaTestKeepAliveNotifyDisconnect() { var client = new TestExtendUaClient(new Uri(ConfigurationManager.AppSettings["UATestEndpoint"])); client.Connect(); var i = 0; client.ServerConnectionLost += (object sender, EventArgs e) => { i++; }; /* Basicallly kill server by not letting any * operations complete */ client.SessionExtended.OperationTimeout = 0; // make sure sessionkeepalive executes at least once client.SessionExtended.KeepAliveInterval = 10; // give ample time to call sessionkeepalive Thread.Sleep(100); /* 'i' should only be one because SessionKeepAlive * only calls ServerConnectionLost if Status * is connected. Before it calls * ServerConnectionLost, it sets Status to * NotConnected */ Assert.AreEqual(1, i); } [Test] public void UaTestReConnect() { var client = new TestExtendUaClient(new Uri(ConfigurationManager.AppSettings["UATestEndpoint"])); /* Should throw error because session should not be * initialized without calling connect */ Assert.Throws<System.NullReferenceException>(() => client.ReConnect()); } [Test] public void UaTestSessionRecreate() { var client = new TestExtendUaClient(new Uri(ConfigurationManager.AppSettings["UATestEndpoint"])); client.Connect(); var i = 0; Session oldSession = null; client.ServerConnectionLost += (object sender, EventArgs e) => { if (i > 0) return; i++; Assert.AreEqual(OpcStatus.NotConnected, client.Status); // store the session to make sure a new one is created oldSession = client.SessionExtended; client.RecreateSession(); // put server back in good working order client.SessionExtended.OperationTimeout = 200; client.SessionExtended.KeepAliveInterval = 100; }; client.SessionExtended.OperationTimeout = 0; client.SessionExtended.KeepAliveInterval = 10; Thread.Sleep(100); Assert.Greater(i, 0); // Give some time to call recreate Thread.Sleep(100); Assert.AreNotSame(oldSession, client.SessionExtended); } [Test] public void UaTestReadTagAsync() { var task = _client.ReadAsync<string>("Server.ServerStatus.BuildInfo.ManufacturerName"); task.Wait(); Assert.AreEqual("OPC Foundation", task.Result.Value); } [Test] public void UaWriteAsync() { const string tag = "Data.Static.Scalar.ByteValue"; var task = _client.WriteAsync(tag, (byte)3); var i = 0; /* task.Wait broken because task is never set * unless exception */ Task.Run(() => { task.Wait(); i++; }); Thread.Sleep(200); Assert.AreEqual(1, i); var val = _client.Read<byte>(tag); Assert.AreEqual(3, val.Value); task = _client.WriteAsync(tag, (byte)13); task.Wait(); val = _client.Read<byte>(tag); Assert.AreEqual(13, val.Value); } [Test] public void UaGetDataType() { var type = _client.GetDataType("Data.Dynamic.Scalar.Int32Value"); Assert.AreEqual(typeof(int), type); type = _client.GetDataType("Data.Dynamic.Scalar.Int16Value"); Assert.AreEqual(typeof(short), type); } } }