diff --git a/Applications/ConsoleReferenceClient/Program.cs b/Applications/ConsoleReferenceClient/Program.cs index 16450caf6..34cbccb86 100644 --- a/Applications/ConsoleReferenceClient/Program.cs +++ b/Applications/ConsoleReferenceClient/Program.cs @@ -83,6 +83,8 @@ public static async Task Main(string[] args) int timeout = Timeout.Infinite; string logFile = null; string reverseConnectUrlString = null; + bool leakChannels = false; + bool forever = false; Mono.Options.OptionSet options = new Mono.Options.OptionSet { usage, @@ -104,6 +106,8 @@ public static async Task Main(string[] args) { "v|verbose", "Verbose output", v => { if (v != null) verbose = true; } }, { "s|subscribe", "Subscribe", s => { if (s != null) subscribe = true; } }, { "rc|reverseconnect=", "Connect using the reverse connect endpoint. (e.g. rc=opc.tcp://localhost:65300)", (string url) => reverseConnectUrlString = url}, + { "forever", "run inner connect/disconnect loop forever", f => { if (f != null) forever = true; } }, + { "leakchannels", "Leave a channel leak open when disconnecting a session.", l => { if (l != null) leakChannels = true; } }, }; ReverseConnectManager reverseConnectManager = null; @@ -189,12 +193,23 @@ public static async Task Main(string[] args) waitTime = timeout - (int)DateTime.UtcNow.Subtract(start).TotalMilliseconds; if (waitTime <= 0) { + if (!forever) + { break; } + else + { + waitTime = 0; } + } - // create the UA Client object and connect to configured server. + if (forever) + { + start = DateTime.UtcNow; + } + } + // create the UA Client object and connect to configured server. using (UAClient uaClient = new UAClient(application.ApplicationConfiguration, reverseConnectManager, output, ClientBase.ValidateResponse) { AutoAccept = autoAccept, SessionLifeTime = 60_000, @@ -308,7 +323,7 @@ public static async Task Main(string[] args) output.WriteLine("Client disconnected."); - uaClient.Disconnect(); + uaClient.Disconnect(leakChannels); } else { diff --git a/Applications/ConsoleReferenceClient/UAClient.cs b/Applications/ConsoleReferenceClient/UAClient.cs index 1e47b4fea..33841c7fb 100644 --- a/Applications/ConsoleReferenceClient/UAClient.cs +++ b/Applications/ConsoleReferenceClient/UAClient.cs @@ -230,7 +230,8 @@ public async Task ConnectAsync(string serverUrl, bool useSecurity = true, /// /// Disconnects the session. /// - public void Disconnect() + /// Leaves the channel open. + public void Disconnect(bool leaveChannelOpen = false) { try { @@ -245,7 +246,12 @@ public void Disconnect() m_reconnectHandler = null; } - m_session.Close(); + m_session.Close(!leaveChannelOpen); + if (leaveChannelOpen) + { + // detach the channel, so it doesn't get closed when the session is disposed. + m_session.DetachChannel(); + } m_session.Dispose(); m_session = null; diff --git a/Applications/ConsoleReferenceServer/Quickstarts.ReferenceServer.Config.xml b/Applications/ConsoleReferenceServer/Quickstarts.ReferenceServer.Config.xml index 7c9a61e2d..6a303e5d8 100644 --- a/Applications/ConsoleReferenceServer/Quickstarts.ReferenceServer.Config.xml +++ b/Applications/ConsoleReferenceServer/Quickstarts.ReferenceServer.Config.xml @@ -69,7 +69,7 @@ 65535 4194304 65535 - 300000 + 30000 3600000 @@ -90,9 +90,9 @@ --> @@ -163,6 +163,7 @@ true 75 + 1000 10000 3600000 10 @@ -229,6 +230,7 @@ http://opcfoundation.org/UA-Profile/Server/ReverseConnect http://opcfoundation.org/UA-Profile/Server/ClientRedundancy + 5 DA @@ -259,10 +261,7 @@ 2500 1000 - 1000 2500 - 1000 - 1000 2500 2500 2500 @@ -270,6 +269,7 @@ 2500 2500 + true diff --git a/Applications/ReferenceServer/Quickstarts.ReferenceServer.Config.xml b/Applications/ReferenceServer/Quickstarts.ReferenceServer.Config.xml index b9d654b44..ad01ec971 100644 --- a/Applications/ReferenceServer/Quickstarts.ReferenceServer.Config.xml +++ b/Applications/ReferenceServer/Quickstarts.ReferenceServer.Config.xml @@ -41,8 +41,8 @@ false - false + only nano and embedded profiles are allowed to use sha1 signed certificates. --> + true true 2048 false @@ -63,13 +63,13 @@ - 600000 + 120000 1048576 1048576 65535 4194304 65535 - 300000 + 30000 3600000 @@ -90,23 +90,27 @@ --> - Sign_2 + SignAndEncrypt_3 http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256 None_1 http://opcfoundation.org/UA/SecurityPolicy#None + + Sign_2 + + SignAndEncrypt_3 - http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256 + - - Sign_2 - http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep - - - SignAndEncrypt_3 - http://opcfoundation.org/UA/SecurityPolicy#Aes128_Sha256_RsaOaep - - - Sign_2 - http://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss - - - SignAndEncrypt_3 - http://opcfoundation.org/UA/SecurityPolicy#Aes256_Sha256_RsaPss - - - Sign_2 - - - - SignAndEncrypt_3 - - 5 @@ -180,7 +160,9 @@ true - 100 + + 75 + 1000 10000 3600000 10 @@ -244,6 +226,8 @@ http://opcfoundation.org/UA-Profile/Server/StandardUA2017 http://opcfoundation.org/UA-Profile/Server/DataAccess http://opcfoundation.org/UA-Profile/Server/Methods + http://opcfoundation.org/UA-Profile/Server/ReverseConnect + http://opcfoundation.org/UA-Profile/Server/ClientRedundancy 5 @@ -256,14 +240,35 @@ 0 false + + + + - 1000 - 1000 - 250 + 2500 + 1000 + 2500 + 2500 2500 - 1000 - 1000 + 2500 + 2500 + 2500 + 2500 + true diff --git a/Libraries/Opc.Ua.Configuration/ApplicationConfigurationBuilder.cs b/Libraries/Opc.Ua.Configuration/ApplicationConfigurationBuilder.cs index fb40e224e..90f3d23f1 100644 --- a/Libraries/Opc.Ua.Configuration/ApplicationConfigurationBuilder.cs +++ b/Libraries/Opc.Ua.Configuration/ApplicationConfigurationBuilder.cs @@ -534,6 +534,13 @@ public IApplicationConfigurationBuilderServerOptions SetMaxSessionCount(int maxS return this; } + /// + public IApplicationConfigurationBuilderServerOptions SetMaxChannelCount(int maxChannelCount) + { + ApplicationConfiguration.ServerConfiguration.MaxChannelCount = maxChannelCount; + return this; + } + /// public IApplicationConfigurationBuilderServerOptions SetMinSessionTimeout(int minSessionTimeout) { diff --git a/Libraries/Opc.Ua.Configuration/IApplicationConfigurationBuilder.cs b/Libraries/Opc.Ua.Configuration/IApplicationConfigurationBuilder.cs index 8884d7d11..b4bbf0440 100644 --- a/Libraries/Opc.Ua.Configuration/IApplicationConfigurationBuilder.cs +++ b/Libraries/Opc.Ua.Configuration/IApplicationConfigurationBuilder.cs @@ -156,6 +156,11 @@ public interface IApplicationConfigurationBuilderServerOptions : /// IApplicationConfigurationBuilderServerOptions SetMaxSessionCount(int maxSessionCount); + /// + /// applies to + /// The lifetime. + IApplicationConfigurationBuilderServerOptions SetMaxChannelCount(int maxChannelCount); + /// IApplicationConfigurationBuilderServerOptions SetMinSessionTimeout(int minSessionTimeout); diff --git a/Libraries/Opc.Ua.Server/Diagnostics/AuditEvents.cs b/Libraries/Opc.Ua.Server/Diagnostics/AuditEvents.cs index 07497f9a4..d5a5aa95d 100644 --- a/Libraries/Opc.Ua.Server/Diagnostics/AuditEvents.cs +++ b/Libraries/Opc.Ua.Server/Diagnostics/AuditEvents.cs @@ -827,7 +827,7 @@ public static class AuditEvents message = new TranslationInfo( "AuditActivateSessionEvent", "en-US", - $"Session with Id:{session.Id} was activated."); + $"Session with Id:{session?.Id} was activated."); } else { diff --git a/Libraries/Opc.Ua.Server/Server/StandardServer.cs b/Libraries/Opc.Ua.Server/Server/StandardServer.cs index a171f6de3..5864bc0d4 100644 --- a/Libraries/Opc.Ua.Server/Server/StandardServer.cs +++ b/Libraries/Opc.Ua.Server/Server/StandardServer.cs @@ -30,6 +30,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Security.Cryptography.X509Certificates; @@ -505,6 +506,7 @@ protected override void Dispose(bool disposing) } Utils.LogInfo("Server - SESSION CREATED. SessionId={0}", sessionId); + // report audit for successful create session ServerInternal.ReportAuditCreateSessionEvent(context?.AuditEntryId, session, revisedSessionTimeout); @@ -2949,6 +2951,9 @@ protected override void StartApplication(ApplicationConfiguration configuration) SessionManager sessionManager = CreateSessionManager(m_serverInternal, configuration); sessionManager.Startup(); + // use event to trigger channel that should not be closed. + sessionManager.SessionChannelKeepAlive += SessionChannelKeepAliveEvent; + // start the subscription manager. Utils.LogInfo(TraceMasks.StartStop, "Server - CreateSubscriptionManager."); SubscriptionManager subscriptionManager = CreateSubscriptionManager(m_serverInternal, configuration); @@ -3086,6 +3091,7 @@ protected override void OnServerStopping() { if (m_serverInternal != null) { + m_serverInternal.SessionManager.SessionChannelKeepAlive -= SessionChannelKeepAliveEvent; m_serverInternal.SubscriptionManager.Shutdown(); m_serverInternal.SessionManager.Shutdown(); m_serverInternal.NodeManager.Shutdown(); @@ -3338,6 +3344,24 @@ public virtual void RemoveNodeManager(INodeManagerFactory nodeManagerFactory) } #endregion + #region Private Methods + /// + /// Reacts to a session channel keep alive event to signal + /// a listener channel that a session is still active. + /// + private void SessionChannelKeepAliveEvent(Session session, SessionEventReason reason) + { + Debug.Assert(reason == SessionEventReason.ChannelKeepAlive); + + string secureChannelId = session?.SecureChannelId; + if (!string.IsNullOrEmpty(secureChannelId)) + { + var transportListener = TransportListeners.FirstOrDefault(tl => secureChannelId.StartsWith(tl.ListenerId, StringComparison.Ordinal)); + transportListener?.UpdateChannelLastActiveTime(secureChannelId); + } + } + #endregion + #region Private Properties private OperationLimitsState OperationLimits => ServerInternal.ServerObject.ServerCapabilities.OperationLimits; #endregion diff --git a/Libraries/Opc.Ua.Server/Session/Session.cs b/Libraries/Opc.Ua.Server/Session/Session.cs index 9d7e384ac..960742b0c 100644 --- a/Libraries/Opc.Ua.Server/Session/Session.cs +++ b/Libraries/Opc.Ua.Server/Session/Session.cs @@ -29,9 +29,7 @@ using System; using System.Collections.Generic; -using System.Text; using System.Security.Cryptography.X509Certificates; -using System.Reflection; namespace Opc.Ua.Server { @@ -346,6 +344,20 @@ public bool HasExpired } } + /// + /// The last time the session was contacted by the client. + /// + public DateTime ClientLastContactTime + { + get + { + lock (DiagnosticsLock) + { + return m_diagnostics.ClientLastContactTime; + } + } + } + /// /// Whether the session has been activated. /// @@ -945,7 +957,7 @@ internal void TraceState(string context) { if (policy.IssuedTokenType == Profiles.JwtUserToken) { - issuedToken.IssuedTokenType = IssuedTokenType.JWT; + issuedToken.IssuedTokenType = IssuedTokenType.JWT; } } diff --git a/Libraries/Opc.Ua.Server/Session/SessionManager.cs b/Libraries/Opc.Ua.Server/Session/SessionManager.cs index 209ba3a5c..ff40d2718 100644 --- a/Libraries/Opc.Ua.Server/Session/SessionManager.cs +++ b/Libraries/Opc.Ua.Server/Session/SessionManager.cs @@ -552,6 +552,7 @@ protected virtual void RaiseSessionEvent(Session session, SessionEventReason rea case SessionEventReason.Created: { handler = m_sessionCreated; break; } case SessionEventReason.Activated: { handler = m_sessionActivated; break; } case SessionEventReason.Closing: { handler = m_sessionClosing; break; } + case SessionEventReason.ChannelKeepAlive: { handler = m_sessionChannelKeepAlive; break; } } if (handler != null) @@ -593,7 +594,8 @@ private void MonitorSessions(object data) for (int ii = 0; ii < sessions.Length; ii++) { - if (sessions[ii].HasExpired) + var session = sessions[ii]; + if (session.HasExpired) { // update diagnostics. lock (m_server.DiagnosticsWriteLock) @@ -606,6 +608,12 @@ private void MonitorSessions(object data) m_server.CloseSession(null, sessions[ii].Id, false); } + // if a session had no activity for the last m_minSessionTimeout milliseconds, send a keep alive event. + else if (session.ClientLastContactTime.AddMilliseconds(m_minSessionTimeout) < DateTime.UtcNow) + { + // signal the channel that the session is still active. + RaiseSessionEvent(session, SessionEventReason.ChannelKeepAlive); + } } if (m_shutdownEvent.WaitOne(sleepCycle)) @@ -642,6 +650,7 @@ private void MonitorSessions(object data) private event SessionEventHandler m_sessionCreated; private event SessionEventHandler m_sessionActivated; private event SessionEventHandler m_sessionClosing; + private event SessionEventHandler m_sessionChannelKeepAlive; private event ImpersonateEventHandler m_impersonateUser; private event EventHandler m_validateSessionLessRequest; #endregion @@ -707,6 +716,26 @@ private void MonitorSessions(object data) } } + /// + public event SessionEventHandler SessionChannelKeepAlive + { + add + { + lock (m_eventLock) + { + m_sessionChannelKeepAlive += value; + } + } + + remove + { + lock (m_eventLock) + { + m_sessionChannelKeepAlive -= value; + } + } + } + /// public event ImpersonateEventHandler ImpersonateUser { @@ -795,6 +824,11 @@ public interface ISessionManager /// event SessionEventHandler SessionClosing; + /// + /// Raised to signal a channel that the session is still alive. + /// + event SessionEventHandler SessionChannelKeepAlive; + /// /// Raised before the user identity for a session is changed. /// @@ -841,7 +875,13 @@ public enum SessionEventReason /// /// A session is about to be closed. /// - Closing + Closing, + + /// + /// A keep alive to signal a channel that the session is still active. + /// Triggered by the session manager based on . + /// + ChannelKeepAlive } /// diff --git a/Stack/Opc.Ua.Bindings.Https/Stack/Https/HttpsTransportListener.cs b/Stack/Opc.Ua.Bindings.Https/Stack/Https/HttpsTransportListener.cs index 754016e0b..30376c74e 100644 --- a/Stack/Opc.Ua.Bindings.Https/Stack/Https/HttpsTransportListener.cs +++ b/Stack/Opc.Ua.Bindings.Https/Stack/Https/HttpsTransportListener.cs @@ -146,11 +146,12 @@ protected virtual void Dispose(bool disposing) #endregion #region ITransportListener Members - /// - /// The URI scheme handled by the listener. - /// + /// public string UriScheme => m_uriScheme; + /// + public string ListenerId => m_listenerId; + /// /// Opens the listener and starts accepting connection. /// @@ -233,6 +234,12 @@ public void CreateReverseConnection(Uri url, int timeout) ConnectionStatusChanged?.Invoke(null, null); throw new NotImplementedException(); } + + /// + public void UpdateChannelLastActiveTime(string globalChannelId) + { + // intentionally not implemented + } #endregion #region Public Methods @@ -307,7 +314,7 @@ public void Stop() { Dispose(); } -#endregion + #endregion #region Private Methods /// diff --git a/Stack/Opc.Ua.Core/Schema/ApplicationConfiguration.cs b/Stack/Opc.Ua.Core/Schema/ApplicationConfiguration.cs index 662f73c7d..831d61c73 100644 --- a/Stack/Opc.Ua.Core/Schema/ApplicationConfiguration.cs +++ b/Stack/Opc.Ua.Core/Schema/ApplicationConfiguration.cs @@ -1451,6 +1451,7 @@ private void Initialize() m_userTokenPolicies = new UserTokenPolicyCollection(); m_diagnosticsEnabled = false; m_maxSessionCount = 100; + m_maxChannelCount = 1000; m_maxSessionTimeout = 3600000; m_minSessionTimeout = 10000; m_maxBrowseContinuationPoints = 10; @@ -1536,12 +1537,23 @@ public int MaxSessionCount set { m_maxSessionCount = value; } } + /// + /// The maximum number of supported secure channels. + /// + /// The channel lifetime. + [DataMember(IsRequired = false, Order = 6)] + public int MaxChannelCount + { + get { return m_maxChannelCount; } + set { m_maxChannelCount = value; } + } + /// /// That minimum period of that a session is allowed to remain /// open without communication from the client (in milliseconds). /// /// The minimum session timeout. - [DataMember(IsRequired = false, Order = 6)] + [DataMember(IsRequired = false, Order = 7)] public int MinSessionTimeout { get { return m_minSessionTimeout; } @@ -1553,7 +1565,7 @@ public int MinSessionTimeout /// open without communication from the client (in milliseconds). /// /// The maximum session timeout. - [DataMember(IsRequired = false, Order = 7)] + [DataMember(IsRequired = false, Order = 8)] public int MaxSessionTimeout { get { return m_maxSessionTimeout; } @@ -1565,7 +1577,7 @@ public int MaxSessionTimeout /// Browse/BrowseNext operations. /// /// The maximum number of continuation points used for Browse/BrowseNext operations - [DataMember(IsRequired = false, Order = 8)] + [DataMember(IsRequired = false, Order = 9)] public int MaxBrowseContinuationPoints { get { return m_maxBrowseContinuationPoints; } @@ -1577,7 +1589,7 @@ public int MaxBrowseContinuationPoints /// Query/QueryNext operations. /// /// The maximum number of query continuation points. - [DataMember(IsRequired = false, Order = 9)] + [DataMember(IsRequired = false, Order = 10)] public int MaxQueryContinuationPoints { get { return m_maxQueryContinuationPoints; } @@ -1588,7 +1600,7 @@ public int MaxQueryContinuationPoints /// The maximum number of continuation points used for HistoryRead operations. /// /// The maximum number of history continuation points. - [DataMember(IsRequired = false, Order = 10)] + [DataMember(IsRequired = false, Order = 11)] public int MaxHistoryContinuationPoints { get { return m_maxHistoryContinuationPoints; } @@ -1599,7 +1611,7 @@ public int MaxHistoryContinuationPoints /// The maximum age of an incoming request (old requests are rejected) (in milliseconds). /// /// The maximum age of an incoming request. - [DataMember(IsRequired = false, Order = 11)] + [DataMember(IsRequired = false, Order = 12)] public int MaxRequestAge { get { return m_maxRequestAge; } @@ -1610,7 +1622,7 @@ public int MaxRequestAge /// The minimum publishing interval supported by the server (in milliseconds). /// /// The minimum publishing interval. - [DataMember(IsRequired = false, Order = 12)] + [DataMember(IsRequired = false, Order = 13)] public int MinPublishingInterval { get { return m_minPublishingInterval; } @@ -1621,7 +1633,7 @@ public int MinPublishingInterval /// The maximum publishing interval supported by the server (in milliseconds). /// /// The maximum publishing interval. - [DataMember(IsRequired = false, Order = 13)] + [DataMember(IsRequired = false, Order = 14)] public int MaxPublishingInterval { get { return m_maxPublishingInterval; } @@ -1632,7 +1644,7 @@ public int MaxPublishingInterval /// The minimum difference between supported publishing interval (in milliseconds). /// /// The publishing resolution. - [DataMember(IsRequired = false, Order = 14)] + [DataMember(IsRequired = false, Order = 15)] public int PublishingResolution { get { return m_publishingResolution; } @@ -1643,7 +1655,7 @@ public int PublishingResolution /// How long the subscriptions will remain open without a publish from the client. /// /// The maximum subscription lifetime. - [DataMember(IsRequired = false, Order = 15)] + [DataMember(IsRequired = false, Order = 16)] public int MaxSubscriptionLifetime { get { return m_maxSubscriptionLifetime; } @@ -1654,7 +1666,7 @@ public int MaxSubscriptionLifetime /// The maximum number of messages saved in the queue for each subscription. /// /// The maximum size of the message queue. - [DataMember(IsRequired = false, Order = 16)] + [DataMember(IsRequired = false, Order = 17)] public int MaxMessageQueueSize { get { return m_maxMessageQueueSize; } @@ -1665,7 +1677,7 @@ public int MaxMessageQueueSize /// The maximum number of notificates saved in the queue for each monitored item. /// /// The maximum size of the notification queue. - [DataMember(IsRequired = false, Order = 17)] + [DataMember(IsRequired = false, Order = 18)] public int MaxNotificationQueueSize { get { return m_maxNotificationQueueSize; } @@ -1676,7 +1688,7 @@ public int MaxNotificationQueueSize /// The maximum number of notifications per publish. /// /// The maximum number of notifications per publish. - [DataMember(IsRequired = false, Order = 18)] + [DataMember(IsRequired = false, Order = 19)] public int MaxNotificationsPerPublish { get { return m_maxNotificationsPerPublish; } @@ -1687,7 +1699,7 @@ public int MaxNotificationsPerPublish /// The minimum sampling interval for metadata. /// /// The minimum sampling interval for metadata. - [DataMember(IsRequired = false, Order = 19)] + [DataMember(IsRequired = false, Order = 20)] public int MinMetadataSamplingInterval { get { return m_minMetadataSamplingInterval; } @@ -1698,7 +1710,7 @@ public int MinMetadataSamplingInterval /// The available sampling rates. /// /// The available sampling rates. - [DataMember(IsRequired = false, EmitDefaultValue = false, Order = 20)] + [DataMember(IsRequired = false, EmitDefaultValue = false, Order = 21)] public SamplingRateGroupCollection AvailableSamplingRates { get { return m_availableSamplingRates; } @@ -1709,7 +1721,7 @@ public SamplingRateGroupCollection AvailableSamplingRates /// The endpoint description for the registration endpoint. /// /// The registration endpoint. - [DataMember(IsRequired = false, EmitDefaultValue = false, Order = 21)] + [DataMember(IsRequired = false, EmitDefaultValue = false, Order = 22)] public EndpointDescription RegistrationEndpoint { get { return m_registrationEndpoint; } @@ -1720,7 +1732,7 @@ public EndpointDescription RegistrationEndpoint /// The maximum time between registration attempts (in milliseconds). /// /// The maximum time between registration attempts (in milliseconds). - [DataMember(IsRequired = false, Order = 22)] + [DataMember(IsRequired = false, Order = 23)] public int MaxRegistrationInterval { get { return m_maxRegistrationInterval; } @@ -1731,7 +1743,7 @@ public int MaxRegistrationInterval /// The path to the file containing nodes persisted by the core node manager. /// /// The path to the file containing nodes persisted by the core node manager. - [DataMember(IsRequired = false, Order = 23)] + [DataMember(IsRequired = false, Order = 24)] public string NodeManagerSaveFile { get { return m_nodeManagerSaveFile; } @@ -1742,7 +1754,7 @@ public string NodeManagerSaveFile /// The minimum lifetime for a subscription (in milliseconds). /// /// The minimum lifetime for a subscription. - [DataMember(IsRequired = false, Order = 24)] + [DataMember(IsRequired = false, Order = 25)] public int MinSubscriptionLifetime { get { return m_minSubscriptionLifetime; } @@ -1753,7 +1765,7 @@ public int MinSubscriptionLifetime /// The max publish request count. /// /// The max publish request count. - [DataMember(IsRequired = false, Order = 25)] + [DataMember(IsRequired = false, Order = 26)] public int MaxPublishRequestCount { get { return m_maxPublishRequestCount; } @@ -1764,7 +1776,7 @@ public int MaxPublishRequestCount /// The max subscription count. /// /// The max subscription count. - [DataMember(IsRequired = false, Order = 26)] + [DataMember(IsRequired = false, Order = 27)] public int MaxSubscriptionCount { get { return m_maxSubscriptionCount; } @@ -1775,7 +1787,7 @@ public int MaxSubscriptionCount /// The max size of the event queue. /// /// The max size of the event queue. - [DataMember(IsRequired = false, Order = 27)] + [DataMember(IsRequired = false, Order = 28)] public int MaxEventQueueSize { get { return m_maxEventQueueSize; } @@ -1786,7 +1798,7 @@ public int MaxEventQueueSize /// The server profile array. /// /// The array of server profiles. - [DataMember(IsRequired = false, Order = 28)] + [DataMember(IsRequired = false, Order = 29)] public StringCollection ServerProfileArray { get { return m_serverProfileArray; } @@ -1804,7 +1816,7 @@ public StringCollection ServerProfileArray /// The server shutdown delay. /// /// The number of seconds to delay the shutdown if a client is connected. - [DataMember(IsRequired = false, Order = 29)] + [DataMember(IsRequired = false, Order = 30)] public int ShutdownDelay { get { return m_shutdownDelay; } @@ -1820,7 +1832,7 @@ public int ShutdownDelay /// here. /// /// The array of server capabilites. - [DataMember(IsRequired = false, Order = 30)] + [DataMember(IsRequired = false, Order = 31)] public StringCollection ServerCapabilities { get { return m_serverCapabilities; } @@ -1838,7 +1850,7 @@ public StringCollection ServerCapabilities /// Gets or sets the supported private key format. /// /// The array of server profiles. - [DataMember(IsRequired = false, Order = 31)] + [DataMember(IsRequired = false, Order = 32)] public StringCollection SupportedPrivateKeyFormats { get { return m_supportedPrivateKeyFormats; } @@ -1855,7 +1867,7 @@ public StringCollection SupportedPrivateKeyFormats /// /// Gets or sets the max size of the trust list. /// - [DataMember(IsRequired = false, Order = 32)] + [DataMember(IsRequired = false, Order = 33)] public int MaxTrustListSize { get { return m_maxTrustListSize; } @@ -1865,7 +1877,7 @@ public int MaxTrustListSize /// /// Gets or sets if multicast DNS is enabled. /// - [DataMember(IsRequired = false, Order = 33)] + [DataMember(IsRequired = false, Order = 34)] public bool MultiCastDnsEnabled { get { return m_multicastDnsEnabled; } @@ -1875,7 +1887,7 @@ public bool MultiCastDnsEnabled /// /// Gets or sets reverse connect server configuration. /// - [DataMember(IsRequired = false, Order = 34)] + [DataMember(IsRequired = false, Order = 35)] public ReverseConnectServerConfiguration ReverseConnect { get { return m_reverseConnect; } @@ -1885,7 +1897,7 @@ public ReverseConnectServerConfiguration ReverseConnect /// /// Gets or sets the operation limits of the OPC UA Server. /// - [DataMember(IsRequired = false, Order = 35)] + [DataMember(IsRequired = false, Order = 36)] public OperationLimits OperationLimits { get { return m_operationLimits; } @@ -1896,7 +1908,7 @@ public OperationLimits OperationLimits /// Whether auditing is enabled. /// /// true if auditing is enabled; otherwise, false. - [DataMember(IsRequired = false, Order = 36)] + [DataMember(IsRequired = false, Order = 37)] public bool AuditingEnabled { get { return m_auditingEnabled; } @@ -1908,6 +1920,7 @@ public bool AuditingEnabled private UserTokenPolicyCollection m_userTokenPolicies; private bool m_diagnosticsEnabled; private int m_maxSessionCount; + private int m_maxChannelCount; private int m_minSessionTimeout; private int m_maxSessionTimeout; private int m_maxBrowseContinuationPoints; diff --git a/Stack/Opc.Ua.Core/Schema/ApplicationConfiguration.xsd b/Stack/Opc.Ua.Core/Schema/ApplicationConfiguration.xsd index dded401d1..2e2ddf6da 100644 --- a/Stack/Opc.Ua.Core/Schema/ApplicationConfiguration.xsd +++ b/Stack/Opc.Ua.Core/Schema/ApplicationConfiguration.xsd @@ -133,6 +133,7 @@ + diff --git a/Stack/Opc.Ua.Core/Stack/Client/ReverseConnectHost.cs b/Stack/Opc.Ua.Core/Stack/Client/ReverseConnectHost.cs index d820dd31f..30b03ec26 100644 --- a/Stack/Opc.Ua.Core/Stack/Client/ReverseConnectHost.cs +++ b/Stack/Opc.Ua.Core/Stack/Client/ReverseConnectHost.cs @@ -69,7 +69,8 @@ public void Open() Factory = null, ServerCertificate = null, ServerCertificateChain = null, - ReverseConnectListener = true + ReverseConnectListener = true, + MaxChannelCount = 0, }; Utils.LogInfo("Open reverse connect listener for {0}.", Url); diff --git a/Stack/Opc.Ua.Core/Stack/Server/ServerBase.cs b/Stack/Opc.Ua.Core/Stack/Server/ServerBase.cs index 1838c033d..9d75de2b0 100644 --- a/Stack/Opc.Ua.Core/Stack/Server/ServerBase.cs +++ b/Stack/Opc.Ua.Core/Stack/Server/ServerBase.cs @@ -830,14 +830,20 @@ ICertificateValidator certificateValidator // create the stack listener. try { - TransportListenerSettings settings = new TransportListenerSettings(); - - settings.Descriptions = endpoints; - settings.Configuration = endpointConfiguration; - settings.ServerCertificate = InstanceCertificate; - settings.CertificateValidator = certificateValidator; - settings.NamespaceUris = MessageContext.NamespaceUris; - settings.Factory = MessageContext.Factory; + TransportListenerSettings settings = new TransportListenerSettings { + Descriptions = endpoints, + Configuration = endpointConfiguration, + ServerCertificate = InstanceCertificate, + CertificateValidator = certificateValidator, + NamespaceUris = MessageContext.NamespaceUris, + Factory = MessageContext.Factory, + MaxChannelCount = 0, + }; + + if (m_configuration is ApplicationConfiguration applicationConfiguration) + { + settings.MaxChannelCount = applicationConfiguration.ServerConfiguration.MaxChannelCount; + } listener.Open( endpointUri, diff --git a/Stack/Opc.Ua.Core/Stack/Tcp/ChannelQuotas.cs b/Stack/Opc.Ua.Core/Stack/Tcp/ChannelQuotas.cs index 06bfd032b..cb5294b2c 100644 --- a/Stack/Opc.Ua.Core/Stack/Tcp/ChannelQuotas.cs +++ b/Stack/Opc.Ua.Core/Stack/Tcp/ChannelQuotas.cs @@ -39,18 +39,12 @@ public IServiceMessageContext MessageContext { get { - lock (m_lock) - { - return m_messageContext; - } + return m_messageContext; } set { - lock (m_lock) - { - m_messageContext = value; - } + m_messageContext = value; } } @@ -61,18 +55,12 @@ public ICertificateValidator CertificateValidator { get { - lock (m_lock) - { - return m_certificateValidator; - } + return m_certificateValidator; } set { - lock (m_lock) - { - m_certificateValidator = value; - } + m_certificateValidator = value; } } @@ -83,18 +71,12 @@ public int MaxMessageSize { get { - lock (m_lock) - { - return m_maxMessageSize; - } + return m_maxMessageSize; } set { - lock (m_lock) - { - m_maxMessageSize = value; - } + m_maxMessageSize = value; } } @@ -105,21 +87,17 @@ public int MaxBufferSize { get { - lock (m_lock) - { - return m_maxBufferSize; - } + return m_maxBufferSize; } set { - lock (m_lock) - { - m_maxBufferSize = value; - } + m_maxBufferSize = value; } } + + /// /// The default lifetime for the channel in milliseconds. /// @@ -127,18 +105,12 @@ public int ChannelLifetime { get { - lock (m_lock) - { - return m_channelLifetime; - } + return m_channelLifetime; } set { - lock (m_lock) - { - m_channelLifetime = value; - } + m_channelLifetime = value; } } @@ -149,24 +121,17 @@ public int SecurityTokenLifetime { get { - lock (m_lock) - { - return m_securityTokenLifetime; - } + return m_securityTokenLifetime; } set { - lock (m_lock) - { - m_securityTokenLifetime = value; - } + m_securityTokenLifetime = value; } } #endregion #region Private Fields - private readonly object m_lock = new object(); private int m_maxMessageSize; private int m_maxBufferSize; private int m_channelLifetime; diff --git a/Stack/Opc.Ua.Core/Stack/Tcp/ITcpChannelListener.cs b/Stack/Opc.Ua.Core/Stack/Tcp/ITcpChannelListener.cs index 159404ce5..0391bbeb3 100644 --- a/Stack/Opc.Ua.Core/Stack/Tcp/ITcpChannelListener.cs +++ b/Stack/Opc.Ua.Core/Stack/Tcp/ITcpChannelListener.cs @@ -11,7 +11,6 @@ */ using System; -using System.Net.Sockets; using System.Security.Cryptography.X509Certificates; using System.Threading.Tasks; diff --git a/Stack/Opc.Ua.Core/Stack/Tcp/TcpListenerChannel.cs b/Stack/Opc.Ua.Core/Stack/Tcp/TcpListenerChannel.cs index c17858404..2eb7a8c90 100644 --- a/Stack/Opc.Ua.Core/Stack/Tcp/TcpListenerChannel.cs +++ b/Stack/Opc.Ua.Core/Stack/Tcp/TcpListenerChannel.cs @@ -11,11 +11,9 @@ */ using System; -using System.Collections.Generic; using System.Net.Sockets; using System.Security.Cryptography.X509Certificates; -using System.Threading; -using System.Threading.Tasks; +using Microsoft.Extensions.Logging; namespace Opc.Ua.Bindings { @@ -62,15 +60,8 @@ public class TcpListenerChannel : UaSCUaBinaryChannel /// /// An overrideable version of the Dispose. /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "m_cleanupTimer")] protected override void Dispose(bool disposing) { - if (disposing) - { - Utils.SilentDispose(m_cleanupTimer); - m_cleanupTimer = null; - } - base.Dispose(disposing); } #endregion @@ -154,10 +145,36 @@ public void Attach(uint channelId, Socket socket) Socket.ReadNextMessage(); - // automatically clean up the channel if no hello received. - StartCleanupTimer(StatusCodes.BadTimeout); } } + + /// + /// Clean up an Opening or Open channel that has been idle for too long. + /// + public void IdleCleanup() + { + TcpChannelState state; + + lock (DataLock) + { + state = State; + if (state == TcpChannelState.Open) + { + state = State = TcpChannelState.Closing; + } + } + + if (state == TcpChannelState.Closing || state == TcpChannelState.Opening || state == TcpChannelState.Faulted) + { + OnCleanup(new ServiceResult(StatusCodes.BadNoCommunication, "Channel closed due to inactivity.")); + } + } + + /// + /// The time in milliseconds elapsed since the channel received or sent messages + /// or received a keep alive. + /// + public int ElapsedSinceLastActiveTime => (HiResClock.TickCount - LastActiveTickCount); #endregion #region Socket Event Handlers @@ -218,13 +235,17 @@ protected void ForceChannelFault(ServiceResult reason) bool close = false; if (State != TcpChannelState.Connecting) { - Utils.LogError( - "{0} ForceChannelFault Socket={1:X8}, ChannelId={2}, TokenId={3}, Reason={4}", - ChannelName, - (Socket != null) ? Socket.Handle : 0, - (CurrentToken != null) ? CurrentToken.ChannelId : 0, - (CurrentToken != null) ? CurrentToken.TokenId : 0, - reason); + int socketHandle = (Socket != null) ? Socket.Handle : 0; + if (socketHandle != -1) + { + Utils.LogError( + "{0} ForceChannelFault Socket={1:X8}, ChannelId={2}, TokenId={3}, Reason={4}", + ChannelName, + socketHandle, + (CurrentToken != null) ? CurrentToken.ChannelId : 0, + (CurrentToken != null) ? CurrentToken.TokenId : 0, + reason); + } } else { @@ -253,31 +274,10 @@ protected void ForceChannelFault(ServiceResult reason) { // notify any monitors. NotifyMonitors(reason, false); - - // ensure the channel will be cleaned up if the client does not reconnect. - StartCleanupTimer(reason); } } } - /// - /// Starts a timer that will clean up the channel if it is not opened/re-opened. - /// - protected void StartCleanupTimer(ServiceResult reason) - { - CleanupTimer(); - m_cleanupTimer = new Timer(OnCleanup, reason, Quotas.ChannelLifetime, Timeout.Infinite); - } - - /// - /// Cleans up a timer that will clean up the channel if it is not opened/re-opened. - /// - protected void CleanupTimer() - { - Utils.SilentDispose(m_cleanupTimer); - m_cleanupTimer = null; - } - /// /// Called when the channel needs to be cleaned up. /// @@ -285,7 +285,6 @@ private void OnCleanup(object state) { lock (DataLock) { - CleanupTimer(); // nothing to do if the channel is now open or closed. if (State == TcpChannelState.Closed || State == TcpChannelState.Open) @@ -300,7 +299,7 @@ private void OnCleanup(object state) reason = new ServiceResult(StatusCodes.BadTimeout); } - Utils.LogTrace( + Utils.LogInfo( "{0} Cleanup Socket={1:X8}, ChannelId={2}, TokenId={3}, Reason={4}", ChannelName, (Socket != null) ? Socket.Handle : 0, @@ -332,8 +331,6 @@ protected void ChannelClosed() // notify any monitors. NotifyMonitors(new ServiceResult(StatusCodes.BadConnectionClosed), true); - - CleanupTimer(); } } @@ -555,7 +552,6 @@ protected uint GetNewTokenId() private ReportAuditCloseSecureChannelEventHandler m_reportAuditCloseSecureChannelEvent; private ReportAuditCertificateEventHandler m_reportAuditCertificateEvent; private long m_lastTokenId; - private Timer m_cleanupTimer; #endregion } diff --git a/Stack/Opc.Ua.Core/Stack/Tcp/TcpReverseConnectChannel.cs b/Stack/Opc.Ua.Core/Stack/Tcp/TcpReverseConnectChannel.cs index 75e85cdb4..da5fe02a1 100644 --- a/Stack/Opc.Ua.Core/Stack/Tcp/TcpReverseConnectChannel.cs +++ b/Stack/Opc.Ua.Core/Stack/Tcp/TcpReverseConnectChannel.cs @@ -114,11 +114,6 @@ private bool ProcessReverseHelloMessage(uint messageType, ArraySegment mes SetResponseRequired(true); ForceChannelFault(StatusCodes.BadTcpMessageTypeInvalid, "The reverse connection was rejected by the client."); } - else - { - // Socket is now owned by client, don't clean up - CleanupTimer(); - } } catch (Exception) { diff --git a/Stack/Opc.Ua.Core/Stack/Tcp/TcpServerChannel.cs b/Stack/Opc.Ua.Core/Stack/Tcp/TcpServerChannel.cs index 3901ddfeb..afbe3ca66 100644 --- a/Stack/Opc.Ua.Core/Stack/Tcp/TcpServerChannel.cs +++ b/Stack/Opc.Ua.Core/Stack/Tcp/TcpServerChannel.cs @@ -65,7 +65,6 @@ public class TcpServerChannel : TcpListenerChannel /// /// An overrideable version of the Dispose. /// - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "m_cleanupTimer")] protected override void Dispose(bool disposing) { base.Dispose(disposing); @@ -230,9 +229,6 @@ private void OnReverseConnectComplete(object sender, IMessageSocketAsyncEventArg ActivateToken(token); State = TcpChannelState.Open; - // no need to cleanup. - CleanupTimer(); - // send response. SendOpenSecureChannelResponse(requestId, token, request); @@ -339,6 +335,9 @@ private bool ProcessHelloMessage(ArraySegment messageChunk) const UInt32 kProtocolVersion = 0; const int kResponseBufferSize = 127; + // Communication is active on the channel + UpdateLastActiveTime(); + // validate the channel state. if (State != TcpChannelState.Connecting) { @@ -478,6 +477,9 @@ private bool ProcessHelloMessage(ArraySegment messageChunk) /// private bool ProcessOpenSecureChannelRequest(uint messageType, ArraySegment messageChunk) { + // Communication is active on the channel + UpdateLastActiveTime(); + // validate the channel state. if (State != TcpChannelState.Opening && State != TcpChannelState.Open) { @@ -802,6 +804,9 @@ private void SendOpenSecureChannelResponse(uint requestId, ChannelToken token, O /// private bool ProcessCloseSecureChannelRequest(uint messageType, ArraySegment messageChunk) { + // Communication is active on the channel + UpdateLastActiveTime(); + // validate security on the message. ChannelToken token = null; uint requestId = 0; @@ -889,6 +894,10 @@ private bool ProcessCloseSecureChannelRequest(uint messageType, ArraySegment private bool ProcessRequestMessage(uint messageType, ArraySegment messageChunk) { + + // Communication is active on the channel + UpdateLastActiveTime(); + // validate the channel state. if (State != TcpChannelState.Open) { diff --git a/Stack/Opc.Ua.Core/Stack/Tcp/TcpTransportListener.cs b/Stack/Opc.Ua.Core/Stack/Tcp/TcpTransportListener.cs index 25df04b5e..8868d1753 100644 --- a/Stack/Opc.Ua.Core/Stack/Tcp/TcpTransportListener.cs +++ b/Stack/Opc.Ua.Core/Stack/Tcp/TcpTransportListener.cs @@ -11,10 +11,13 @@ */ using System; +using System.Collections.Concurrent; using System.Collections.Generic; +using System.Linq; using System.Net; using System.Net.Sockets; using System.Security.Cryptography.X509Certificates; +using System.Threading; using System.Threading.Tasks; namespace Opc.Ua.Bindings @@ -39,6 +42,9 @@ public override ITransportListener Create() /// public class TcpTransportListener : ITransportListener, ITcpChannelListener { + // The limit of queued connections for the listener socket.. + const int kSocketBacklog = 10; + #region IDisposable Members /// /// Frees any unmanaged resources. @@ -58,6 +64,12 @@ protected virtual void Dispose(bool disposing) { lock (m_lock) { + if (m_inactivityDetectionTimer != null) + { + Utils.SilentDispose(m_inactivityDetectionTimer); + m_inactivityDetectionTimer = null; + } + if (m_listeningSocket != null) { Utils.SilentDispose(m_listeningSocket); @@ -89,6 +101,11 @@ protected virtual void Dispose(bool disposing) /// public string UriScheme => Utils.UriSchemeOpcTcp; + /// + /// The Id of the transport listener. + /// + public string ListenerId => m_listenerId; + /// /// Opens the listener and starts accepting connection. /// @@ -119,6 +136,7 @@ protected virtual void Dispose(bool disposing) if (configuration != null) { + m_inactivityDetectPeriod = configuration.ChannelLifetime / 2; m_quotas.MaxBufferSize = configuration.MaxBufferSize; m_quotas.MaxMessageSize = configuration.MaxMessageSize; m_quotas.ChannelLifetime = configuration.ChannelLifetime; @@ -139,6 +157,7 @@ protected virtual void Dispose(bool disposing) m_bufferManager = new BufferManager("Server", m_quotas.MaxBufferSize); m_channels = new Dictionary(); m_reverseConnectListener = settings.ReverseConnectListener; + m_maxChannelCount = settings.MaxChannelCount; // save the callback to the server. m_callback = callback; @@ -155,6 +174,26 @@ public void Close() { Stop(); } + + /// + public void UpdateChannelLastActiveTime(string globalChannelId) + { + try + { + var channelIdString = globalChannelId.Substring(ListenerId.Length + 1); + var channelId = Convert.ToUInt32(channelIdString); + + if (channelId > 0 && + m_channels.TryGetValue(channelId, out TcpListenerChannel channel)) + { + channel?.UpdateLastActiveTime(); + } + } + catch + { + // ignore errors for calls with invalid channel id + } + } #endregion #region ITcpChannelListener @@ -199,10 +238,7 @@ public void ChannelClosed(uint channelId) { lock (m_lock) { - if (m_channels != null) - { - m_channels.Remove(channelId); - } + m_channels?.Remove(channelId); } Utils.LogInfo("ChannelId {0}: closed", channelId); @@ -310,7 +346,13 @@ public void Start() args.Completed += OnAccept; args.UserToken = m_listeningSocket; m_listeningSocket.Bind(endpoint); - m_listeningSocket.Listen(Int32.MaxValue); + m_listeningSocket.Listen(kSocketBacklog); + + m_inactivityDetectionTimer = new Timer(DetectInactiveChannels, + null, + m_inactivityDetectPeriod, + m_inactivityDetectPeriod); + if (!m_listeningSocket.AcceptAsync(args)) { OnAccept(null, args); @@ -481,8 +523,16 @@ private void OnAccept(object sender, SocketAsyncEventArgs e) return; } + bool serveChannel = !(m_maxChannelCount > 0 && m_maxChannelCount < m_channels.Count); + if (!serveChannel) + { + Utils.LogError("OnAccept: Maximum number of channels {0} reached, serving channels is stopped until number is lower or equal than {1} ", + m_channels.Count, m_maxChannelCount); + Utils.SilentDispose(e.AcceptSocket); + } + // check if the accept socket has been created. - if (e.AcceptSocket != null && e.SocketError == SocketError.Success) + if (serveChannel && e.AcceptSocket != null && e.SocketError == SocketError.Success) { try { @@ -555,6 +605,46 @@ private void OnAccept(object sender, SocketAsyncEventArgs e) } } while (repeatAccept); } + + /// + /// The inactive timer callback which detects stale channels. + /// + /// + private void DetectInactiveChannels(object state = null) + { + List channels; + + lock (m_lock) + { + channels = new List(); + foreach (var chEntry in m_channels) + { + if (chEntry.Value.ElapsedSinceLastActiveTime > m_quotas.ChannelLifetime) + { + channels.Add(chEntry.Value); + } + } + } + + if (channels.Count > 0) + { + Utils.LogInfo("TCPLISTENER: {0} channels scheduled for IdleCleanup.", channels.Count); + foreach (var channel in channels) + { + lock (m_lock) + { + channel.IdleCleanup(); + } + } + } + } + #endregion + + #region Public Fields + /// + /// The maximum number of secure channels + /// + public int MaxChannelCount => m_maxChannelCount; #endregion #region Private Methods @@ -664,7 +754,7 @@ private uint GetNextChannelId() do { uint nextChannelId = ++m_lastChannelId; - if (!m_channels.ContainsKey(nextChannelId)) + if (nextChannelId != 0 && !m_channels.ContainsKey(nextChannelId)) { return nextChannelId; } @@ -672,6 +762,7 @@ private uint GetNextChannelId() } } + /// /// Sets the URI for the listener. /// @@ -722,6 +813,9 @@ private void SetUri(Uri baseAddress, string relativeAddress) private Dictionary m_channels; private ITransportListenerCallback m_callback; private bool m_reverseConnectListener; + private int m_inactivityDetectPeriod; + private Timer m_inactivityDetectionTimer; + private int m_maxChannelCount; #endregion } diff --git a/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryChannel.Symmetric.cs b/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryChannel.Symmetric.cs index 7b5bbf681..8a327d19b 100644 --- a/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryChannel.Symmetric.cs +++ b/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryChannel.Symmetric.cs @@ -446,10 +446,7 @@ protected void ComputeKeys(ChannelToken token) { if (!success) { - if (chunksToProcess != null) - { - chunksToProcess.Release(BufferManager, "WriteSymmetricMessage"); - } + chunksToProcess?.Release(BufferManager, "WriteSymmetricMessage"); } } } diff --git a/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryChannel.cs b/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryChannel.cs index d60c80382..07edeca52 100644 --- a/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryChannel.cs +++ b/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryChannel.cs @@ -194,6 +194,11 @@ public void SetStateChangedCallback(TcpChannelStateEventHandler callback) m_StateChanged = callback; } } + + /// + /// The tickcount in milliseconds when the channel received/sent the last message. + /// + protected int LastActiveTickCount => m_lastActiveTickCount; #endregion #region Channel State Functions @@ -204,9 +209,13 @@ protected void ChannelStateChanged(TcpChannelState state, ServiceResult reason) { if (m_StateChanged != null) { - Task.Run(() => { - m_StateChanged?.Invoke(this, state, reason); - }); + var stateChanged = m_StateChanged; + if (stateChanged != null) + { + Task.Run(() => { + stateChanged?.Invoke(this, state, reason); + }); + } } } @@ -310,11 +319,7 @@ protected BufferCollection GetSavedChunks(uint requestId, ArraySegment chu /// protected int GetSavedChunksTotalSize() { - if (m_partialMessageChunks != null) - { - return m_partialMessageChunks.TotalSize; - } - return 0; + return m_partialMessageChunks?.TotalSize ?? 0; } /// @@ -523,10 +528,10 @@ protected void BeginWriteMessage(BufferCollection buffers, object state) /// protected virtual void HandleWriteComplete(BufferCollection buffers, object state, int bytesWritten, ServiceResult result) { - if (buffers != null) - { - buffers.Release(BufferManager, "WriteOperation"); - } + // Communication is active on the channel + UpdateLastActiveTime(); + + buffers?.Release(BufferManager, "WriteOperation"); Interlocked.Decrement(ref m_activeWriteRequests); } @@ -535,7 +540,7 @@ protected virtual void HandleWriteComplete(BufferCollection buffers, object stat /// protected static void WriteErrorMessageBody(BinaryEncoder encoder, ServiceResult error) { - string reason = (error.LocalizedText != null) ? error.LocalizedText.Text : null; + string reason = error.LocalizedText?.Text; // check that length is not exceeded. if (reason != null) @@ -826,6 +831,14 @@ protected static int CalculateChunkCount(int messageSize, int bufferSize) } return 1; } + + /// + /// Update the last time that communication has occured on the channel. + /// + public void UpdateLastActiveTime() + { + m_lastActiveTickCount = HiResClock.TickCount; + } #endregion #region Private Fields @@ -852,6 +865,8 @@ protected static int CalculateChunkCount(int messageSize, int bufferSize) private BufferCollection m_partialMessageChunks; private TcpChannelStateEventHandler m_StateChanged; + + private int m_lastActiveTickCount; #endregion } @@ -888,7 +903,7 @@ public enum TcpChannelState /// /// The channel is in a error state. /// - Faulted + Faulted, } /// diff --git a/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryClientChannel.cs b/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryClientChannel.cs index 48ddbd12b..2a06f5103 100644 --- a/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryClientChannel.cs +++ b/Stack/Opc.Ua.Core/Stack/Tcp/UaSCBinaryClientChannel.cs @@ -582,10 +582,7 @@ private void SendOpenSecureChannelRequest(bool renew) } finally { - if (chunksToSend != null) - { - chunksToSend.Release(BufferManager, "SendOpenSecureChannelRequest"); - } + chunksToSend?.Release(BufferManager, "SendOpenSecureChannelRequest"); } } @@ -714,10 +711,7 @@ private bool ProcessOpenSecureChannelResponse(uint messageType, ArraySegment message } finally { - if (chunksToProcess != null) - { - chunksToProcess.Release(BufferManager, "ProcessResponseMessage"); - } + chunksToProcess?.Release(BufferManager, "ProcessResponseMessage"); } } #endregion diff --git a/Stack/Opc.Ua.Core/Stack/Transport/ITransportListener.cs b/Stack/Opc.Ua.Core/Stack/Transport/ITransportListener.cs index 29a242dc7..9746bd25c 100644 --- a/Stack/Opc.Ua.Core/Stack/Transport/ITransportListener.cs +++ b/Stack/Opc.Ua.Core/Stack/Transport/ITransportListener.cs @@ -27,6 +27,11 @@ namespace Opc.Ua /// public interface ITransportListener : IDisposable { + /// + /// The Id of the transport listener. + /// + string ListenerId { get; } + /// /// The protocol supported by the listener. /// @@ -75,6 +80,12 @@ ITransportListenerCallback callback /// void CreateReverseConnection(Uri url, int timeout); + /// + /// Updates the last active time of a global channel to defer + /// clean up based on channel timeout. + /// + /// The global channel id + void UpdateChannelLastActiveTime(string globalChannelId); } /// diff --git a/Stack/Opc.Ua.Core/Stack/Transport/TransportListenerSettings.cs b/Stack/Opc.Ua.Core/Stack/Transport/TransportListenerSettings.cs index 40d90f43f..a67ce0f4d 100644 --- a/Stack/Opc.Ua.Core/Stack/Transport/TransportListenerSettings.cs +++ b/Stack/Opc.Ua.Core/Stack/Transport/TransportListenerSettings.cs @@ -117,6 +117,16 @@ public bool ReverseConnectListener get { return m_reverseConnectListener; } set { m_reverseConnectListener = value; } } + + /// + /// Indicates the max number of channels that can be created by the listener. + /// 0 indictates no limit. + /// + public int MaxChannelCount + { + get { return m_maxChannelCount; } + set { m_maxChannelCount = value; } + } #endregion #region Private Fields @@ -128,6 +138,7 @@ public bool ReverseConnectListener private NamespaceTable m_namespaceUris; private IEncodeableFactory m_channelFactory; private bool m_reverseConnectListener; + private int m_maxChannelCount; #endregion } } diff --git a/Stack/Opc.Ua.Core/Types/Utils/HiResClock.cs b/Stack/Opc.Ua.Core/Types/Utils/HiResClock.cs index 513bd0100..d4cf87edc 100644 --- a/Stack/Opc.Ua.Core/Types/Utils/HiResClock.cs +++ b/Stack/Opc.Ua.Core/Types/Utils/HiResClock.cs @@ -68,6 +68,19 @@ public static long TickCount64 /// public static double TicksPerMillisecond => s_Default.m_ticksPerMillisecond; + /// + /// A monotonic tick count in milliseconds as a 32 bit signed number. + /// It starts at 0 when the system starts. + /// After 24.9 days it wraps around to negative numbers. + /// It wraps around completely every 49.7 days. + /// + /// + /// It's resolution might not be the highest, typically it is based on a system timer @16ms. + /// Use for relative time measurements which do not require a high resolution and + /// which should be independent of the system time, which can be changed by a user. + /// + public static int TickCount => Environment.TickCount; + /// /// Disables the hires clock. /// diff --git a/Tests/Opc.Ua.Client.ComplexTypes.Tests/Opc.Ua.Client.ComplexTypes.Tests.csproj b/Tests/Opc.Ua.Client.ComplexTypes.Tests/Opc.Ua.Client.ComplexTypes.Tests.csproj index bb2402572..b80e985a0 100644 --- a/Tests/Opc.Ua.Client.ComplexTypes.Tests/Opc.Ua.Client.ComplexTypes.Tests.csproj +++ b/Tests/Opc.Ua.Client.ComplexTypes.Tests/Opc.Ua.Client.ComplexTypes.Tests.csproj @@ -8,7 +8,7 @@ - + all diff --git a/Tests/Opc.Ua.Client.ComplexTypes.Tests/TypeSystemClientTest.cs b/Tests/Opc.Ua.Client.ComplexTypes.Tests/TypeSystemClientTest.cs index c6d5ffc64..d77cdb0c5 100644 --- a/Tests/Opc.Ua.Client.ComplexTypes.Tests/TypeSystemClientTest.cs +++ b/Tests/Opc.Ua.Client.ComplexTypes.Tests/TypeSystemClientTest.cs @@ -40,6 +40,8 @@ using Opc.Ua.Server.Tests; using Quickstarts; using Quickstarts.ReferenceServer; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Client.ComplexTypes.Tests { @@ -124,7 +126,7 @@ public async Task OneTimeSetUpAsync(TextWriter writer = null) } catch (Exception e) { - Assert.Ignore("OneTimeSetup failed to create session, tests skipped. Error: {0}", e.Message); + Assert.Ignore($"OneTimeSetup failed to create session, tests skipped. Error: {e.Message}"); } } diff --git a/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/ComplexTypesCommon.cs b/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/ComplexTypesCommon.cs index 75562af6f..d47d71b6d 100644 --- a/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/ComplexTypesCommon.cs +++ b/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/ComplexTypesCommon.cs @@ -37,6 +37,7 @@ using NUnit.Framework; using Opc.Ua.Core.Tests.Types.Encoders; using Opc.Ua.Test; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Client.ComplexTypes.Tests.Types { diff --git a/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/ComplexTypesTests.cs b/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/ComplexTypesTests.cs index f91cb7db1..6ff8ba107 100644 --- a/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/ComplexTypesTests.cs +++ b/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/ComplexTypesTests.cs @@ -30,6 +30,7 @@ using System; using NUnit.Framework; using Opc.Ua.Core.Tests.Types.Encoders; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Client.ComplexTypes.Tests.Types { diff --git a/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/JsonEncoderTests.cs b/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/JsonEncoderTests.cs index 5f12fea60..833fb7991 100644 --- a/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/JsonEncoderTests.cs +++ b/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/JsonEncoderTests.cs @@ -35,6 +35,7 @@ using Newtonsoft.Json.Linq; using NUnit.Framework; using Opc.Ua.Core.Tests.Types.Encoders; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Client.ComplexTypes.Tests.Types { diff --git a/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/MockResolverTests.cs b/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/MockResolverTests.cs index 3b822c94e..553dece67 100644 --- a/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/MockResolverTests.cs +++ b/Tests/Opc.Ua.Client.ComplexTypes.Tests/Types/MockResolverTests.cs @@ -37,6 +37,7 @@ using System.Threading.Tasks; using NUnit.Framework; using Opc.Ua.Core.Tests.Types.Encoders; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Client.ComplexTypes.Tests.Types { @@ -681,7 +682,7 @@ private object GetRandom(NodeId valueType) } else { - Assert.Fail("Unexpected ValueType {0}", valueType); + Assert.Fail($"Unexpected ValueType {valueType}"); } return null; } diff --git a/Tests/Opc.Ua.Client.Tests/ClientTest.cs b/Tests/Opc.Ua.Client.Tests/ClientTest.cs index 9d35aecc8..116f01971 100644 --- a/Tests/Opc.Ua.Client.Tests/ClientTest.cs +++ b/Tests/Opc.Ua.Client.Tests/ClientTest.cs @@ -41,8 +41,11 @@ using Moq; using Newtonsoft.Json.Linq; using NUnit.Framework; +using Opc.Ua.Bindings; using Opc.Ua.Configuration; using Opc.Ua.Server.Tests; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Client.Tests { @@ -282,7 +285,7 @@ public void ReadOnDiscoveryChannel(int readCount) // client may report channel closed instead of security policy rejected if (StatusCodes.BadSecureChannelClosed == sre.StatusCode) { - Assert.Inconclusive("Unexpected Status: {0}", sre); + Assert.Inconclusive($"Unexpected Status: {sre}" ); } Assert.AreEqual(StatusCodes.BadSecurityPolicyRejected, sre.StatusCode, "Unexpected Status: {0}", sre); } @@ -311,7 +314,7 @@ public void GetEndpointsOnDiscoveryChannel() // client may report channel closed instead of security policy rejected if (StatusCodes.BadSecureChannelClosed == sre.StatusCode) { - Assert.Inconclusive("Unexpected Status: {0}", sre); + Assert.Inconclusive($"Unexpected Status: {sre}" ); } Assert.AreEqual(StatusCodes.BadSecurityPolicyRejected, sre.StatusCode, "Unexpected Status: {0}", sre); } @@ -367,7 +370,34 @@ public async Task ConnectAndCloseAsyncReadAfterClose() var node = await session.ReadNodeAsync(nodeId, CancellationToken.None).ConfigureAwait(false); var value = await session.ReadValueAsync(nodeId, CancellationToken.None).ConfigureAwait(false); - // keep channel open + // keep channel open/inactive + var result = await session.CloseAsync(1_000, false).ConfigureAwait(false); + Assert.AreEqual((StatusCode)StatusCodes.Good, result); + + await Task.Delay(5_000).ConfigureAwait(false); + + var sre = Assert.ThrowsAsync(async () => await session.ReadNodeAsync(nodeId, CancellationToken.None).ConfigureAwait(false)); + Assert.AreEqual((StatusCode)StatusCodes.BadSessionIdInvalid, sre.StatusCode); + } + } + + [Test, Order(204)] + public async Task ConnectAndCloseAsyncReadAfterCloseSessionReconnect() + { + var securityPolicy = SecurityPolicies.Basic256Sha256; + using (var session = await ClientFixture.ConnectAsync(ServerUrl, securityPolicy, Endpoints).ConfigureAwait(false)) + { + Assert.NotNull(session); + Session.SessionClosing += Session_Closing; + + var userIdentity = session.Identity; + var sessionName = session.SessionName; + + var nodeId = new NodeId(Opc.Ua.VariableIds.ServerStatusType_BuildInfo); + var node = await session.ReadNodeAsync(nodeId, CancellationToken.None).ConfigureAwait(false); + var value = await session.ReadValueAsync(nodeId, CancellationToken.None).ConfigureAwait(false); + + // keep channel open/inactive var result = await session.CloseAsync(1_000, false).ConfigureAwait(false); Assert.AreEqual((StatusCode)StatusCodes.Good, result); @@ -375,6 +405,45 @@ public async Task ConnectAndCloseAsyncReadAfterClose() var sre = Assert.ThrowsAsync(async () => await session.ReadNodeAsync(nodeId, CancellationToken.None).ConfigureAwait(false)); Assert.AreEqual((StatusCode)StatusCodes.BadSessionIdInvalid, sre.StatusCode); + + // reconect/reactivate + await session.OpenAsync(sessionName, userIdentity, CancellationToken.None).ConfigureAwait(false); + + node = await session.ReadNodeAsync(nodeId, CancellationToken.None).ConfigureAwait(false); + value = await session.ReadValueAsync(nodeId, CancellationToken.None).ConfigureAwait(false); + } + } + + [Test, Order(206)] + public async Task ConnectCloseSessionCloseChannel() + { + var securityPolicy = SecurityPolicies.Basic256Sha256; + using (var session = await ClientFixture.ConnectAsync(ServerUrl, securityPolicy, Endpoints).ConfigureAwait(false)) + { + + Assert.NotNull(session); + Session.SessionClosing += Session_Closing; + + var userIdentity = session.Identity; + var sessionName = session.SessionName; + + var nodeId = new NodeId(Opc.Ua.VariableIds.ServerStatusType_BuildInfo); + var node = await session.ReadNodeAsync(nodeId, CancellationToken.None).ConfigureAwait(false); + var value = await session.ReadValueAsync(nodeId, CancellationToken.None).ConfigureAwait(false); + + // keep channel opened but detach so no comm goes through + var channel = session.TransportChannel; + session.DetachChannel(); + + int waitTime = ServerFixture.Application.ApplicationConfiguration.TransportQuotas.ChannelLifetime + + (ServerFixture.Application.ApplicationConfiguration.TransportQuotas.ChannelLifetime / 2) + 5_000; + await Task.Delay(waitTime).ConfigureAwait(false); + + // Channel handling checked for TcpTransportChannel only + if (channel is TcpTransportChannel tcp) + { + Assert.IsNull(tcp.Socket); + } } } diff --git a/Tests/Opc.Ua.Client.Tests/ClientTestFramework.cs b/Tests/Opc.Ua.Client.Tests/ClientTestFramework.cs index 127529967..8e72573a6 100644 --- a/Tests/Opc.Ua.Client.Tests/ClientTestFramework.cs +++ b/Tests/Opc.Ua.Client.Tests/ClientTestFramework.cs @@ -38,6 +38,7 @@ using NUnit.Framework; using Opc.Ua.Server.Tests; using Quickstarts.ReferenceServer; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Client.Tests { @@ -187,7 +188,7 @@ public async Task OneTimeSetUpAsync(TextWriter writer = null, bool securityNone } catch (Exception e) { - Assert.Warn("OneTimeSetup failed to create session with {0}, tests fail. Error: {1}", ServerUrl, e.Message); + Assert.Warn($"OneTimeSetup failed to create session with {ServerUrl}, tests fail. Error: {e.Message}"); } } } @@ -224,7 +225,7 @@ public async Task SetUp() } catch (Exception e) { - Assert.Ignore("OneTimeSetup failed to create session, tests skipped. Error: {0}", e.Message); + Assert.Ignore($"OneTimeSetup failed to create session, tests skipped. Error: {e.Message}"); } } if (ServerFixture == null) diff --git a/Tests/Opc.Ua.Client.Tests/NodeCacheAsyncTest.cs b/Tests/Opc.Ua.Client.Tests/NodeCacheAsyncTest.cs index bfe0dc13d..160686c5a 100644 --- a/Tests/Opc.Ua.Client.Tests/NodeCacheAsyncTest.cs +++ b/Tests/Opc.Ua.Client.Tests/NodeCacheAsyncTest.cs @@ -35,6 +35,8 @@ using BenchmarkDotNet.Attributes; using NUnit.Framework; using Opc.Ua.Server.Tests; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Client.Tests { diff --git a/Tests/Opc.Ua.Client.Tests/NodeCacheTest.cs b/Tests/Opc.Ua.Client.Tests/NodeCacheTest.cs index 9640042b7..012383f11 100644 --- a/Tests/Opc.Ua.Client.Tests/NodeCacheTest.cs +++ b/Tests/Opc.Ua.Client.Tests/NodeCacheTest.cs @@ -35,6 +35,8 @@ using BenchmarkDotNet.Attributes; using NUnit.Framework; using Opc.Ua.Server.Tests; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Client.Tests { diff --git a/Tests/Opc.Ua.Client.Tests/Opc.Ua.Client.Tests.csproj b/Tests/Opc.Ua.Client.Tests/Opc.Ua.Client.Tests.csproj index f4aa4733f..1cec7bbba 100644 --- a/Tests/Opc.Ua.Client.Tests/Opc.Ua.Client.Tests.csproj +++ b/Tests/Opc.Ua.Client.Tests/Opc.Ua.Client.Tests.csproj @@ -10,7 +10,7 @@ - + all diff --git a/Tests/Opc.Ua.Client.Tests/RequestHeaderTest.cs b/Tests/Opc.Ua.Client.Tests/RequestHeaderTest.cs index eb7cc2f95..40a453559 100644 --- a/Tests/Opc.Ua.Client.Tests/RequestHeaderTest.cs +++ b/Tests/Opc.Ua.Client.Tests/RequestHeaderTest.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Client.Tests { diff --git a/Tests/Opc.Ua.Client.Tests/ReverseConnectTest.cs b/Tests/Opc.Ua.Client.Tests/ReverseConnectTest.cs index e277b587f..e0ca3ec33 100644 --- a/Tests/Opc.Ua.Client.Tests/ReverseConnectTest.cs +++ b/Tests/Opc.Ua.Client.Tests/ReverseConnectTest.cs @@ -36,6 +36,8 @@ using NUnit.Framework; using Opc.Ua.Server.Tests; using Quickstarts.ReferenceServer; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Client.Tests { diff --git a/Tests/Opc.Ua.Client.Tests/SessionClientBatchTest.cs b/Tests/Opc.Ua.Client.Tests/SessionClientBatchTest.cs index b17d13709..a323ce9d5 100644 --- a/Tests/Opc.Ua.Client.Tests/SessionClientBatchTest.cs +++ b/Tests/Opc.Ua.Client.Tests/SessionClientBatchTest.cs @@ -34,6 +34,8 @@ using BenchmarkDotNet.Attributes; using NUnit.Framework; using Opc.Ua.Server.Tests; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Client.Tests { diff --git a/Tests/Opc.Ua.Client.Tests/SubscriptionTest.cs b/Tests/Opc.Ua.Client.Tests/SubscriptionTest.cs index 10382230d..4fac0ea58 100644 --- a/Tests/Opc.Ua.Client.Tests/SubscriptionTest.cs +++ b/Tests/Opc.Ua.Client.Tests/SubscriptionTest.cs @@ -37,6 +37,8 @@ using System.Threading; using System.Threading.Tasks; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Client.Tests { @@ -303,7 +305,7 @@ public async Task AddSubscriptionAsync() [Test, Order(200)] public async Task LoadSubscriptionAsync() { - if (!File.Exists(m_subscriptionTestXml)) Assert.Ignore("Save file {0} does not exist yet", m_subscriptionTestXml); + if (!File.Exists(m_subscriptionTestXml)) Assert.Ignore($"Save file {m_subscriptionTestXml} does not exist yet"); // load var subscriptions = Session.Load(m_subscriptionTestXml, false, new[] { typeof(TestableSubscription) }); @@ -343,7 +345,7 @@ public async Task LoadSubscriptionAsync() } [Theory, Order(300)] - [Timeout(30_000)] + [CancelAfter(30_000)] /// /// This test doesn't deterministically prove sequential publishing, /// but rather relies on a subscription not being able to handle the message load. @@ -694,7 +696,7 @@ public void SequentialPublishingSubscription(bool enabled) } [Test, Order(400)] - [Timeout(30_000)] + [CancelAfter(30_000)] public async Task PublishRequestCount() { var subscriptionList = new List(); diff --git a/Tests/Opc.Ua.Client.Tests/TraceableRequestHeaderTest.cs b/Tests/Opc.Ua.Client.Tests/TraceableRequestHeaderTest.cs index cd834bdb9..17bc9a607 100644 --- a/Tests/Opc.Ua.Client.Tests/TraceableRequestHeaderTest.cs +++ b/Tests/Opc.Ua.Client.Tests/TraceableRequestHeaderTest.cs @@ -5,6 +5,8 @@ using System.Threading.Tasks; using BenchmarkDotNet.Attributes; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Client.Tests { diff --git a/Tests/Opc.Ua.Configuration.Tests/ApplicationInstanceTests.cs b/Tests/Opc.Ua.Configuration.Tests/ApplicationInstanceTests.cs index cefcfb84e..922ec992a 100644 --- a/Tests/Opc.Ua.Configuration.Tests/ApplicationInstanceTests.cs +++ b/Tests/Opc.Ua.Configuration.Tests/ApplicationInstanceTests.cs @@ -35,6 +35,7 @@ using System.Threading; using System.Threading.Tasks; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Configuration.Tests { diff --git a/Tests/Opc.Ua.Configuration.Tests/CertificateStoreTypeTest.cs b/Tests/Opc.Ua.Configuration.Tests/CertificateStoreTypeTest.cs index 346dbcdcf..ce3591ff8 100644 --- a/Tests/Opc.Ua.Configuration.Tests/CertificateStoreTypeTest.cs +++ b/Tests/Opc.Ua.Configuration.Tests/CertificateStoreTypeTest.cs @@ -34,6 +34,7 @@ using System.Threading.Tasks; using NUnit.Framework; using Opc.Ua.Security.Certificates; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Configuration.Tests { diff --git a/Tests/Opc.Ua.Configuration.Tests/Opc.Ua.Configuration.Tests.csproj b/Tests/Opc.Ua.Configuration.Tests/Opc.Ua.Configuration.Tests.csproj index ad10318d1..b4c571b42 100644 --- a/Tests/Opc.Ua.Configuration.Tests/Opc.Ua.Configuration.Tests.csproj +++ b/Tests/Opc.Ua.Configuration.Tests/Opc.Ua.Configuration.Tests.csproj @@ -9,7 +9,7 @@ - + all diff --git a/Tests/Opc.Ua.Core.Tests/Opc.Ua.Core.Tests.csproj b/Tests/Opc.Ua.Core.Tests/Opc.Ua.Core.Tests.csproj index 5cfd6d209..ed4d68faf 100644 --- a/Tests/Opc.Ua.Core.Tests/Opc.Ua.Core.Tests.csproj +++ b/Tests/Opc.Ua.Core.Tests/Opc.Ua.Core.Tests.csproj @@ -12,7 +12,7 @@ - + all diff --git a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateFactoryTest.cs b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateFactoryTest.cs index fcab02e03..b6e28a798 100644 --- a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateFactoryTest.cs +++ b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateFactoryTest.cs @@ -37,6 +37,8 @@ using NUnit.Framework; using Opc.Ua.Security.Certificates; using Opc.Ua.Security.Certificates.Tests; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Security.Certificates { diff --git a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateStoreTest.cs b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateStoreTest.cs index 633e4d976..fdc220e0f 100644 --- a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateStoreTest.cs +++ b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateStoreTest.cs @@ -38,6 +38,8 @@ using NUnit.Framework; using Opc.Ua.Security.Certificates; using Opc.Ua.X509StoreExtensions; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Security.Certificates { diff --git a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateStoreTypeTest.cs b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateStoreTypeTest.cs index 7b77554c0..a53cb5731 100644 --- a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateStoreTypeTest.cs +++ b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateStoreTypeTest.cs @@ -4,6 +4,8 @@ using System.Threading.Tasks; using NUnit.Framework; using Opc.Ua.Security.Certificates; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Security.Certificates { diff --git a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorAlternate.cs b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorAlternate.cs index 425d61dad..5c1ea46e6 100644 --- a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorAlternate.cs +++ b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorAlternate.cs @@ -41,6 +41,8 @@ using EmbedIO.Actions; using NUnit.Framework; using Opc.Ua.Security.Certificates; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + #if !ECC_SUPPORT using X509SignatureGenerator = Opc.Ua.Security.Certificates.X509SignatureGenerator; #endif @@ -145,7 +147,7 @@ public async Task OneTimeSetUpAsync() } catch { - Assert.Ignore("Web server could not start at: {0}", m_webServerUrl); + Assert.Ignore($"Web server could not start at: {m_webServerUrl}"); } } @@ -304,7 +306,7 @@ public void AlternateRootCertificateWithAuthorityKeyID(bool subjectKeyIdentifier /// /// Validate a chain with a loop is detected. /// - [Test, Timeout(10000)] + [Test, CancelAfter(10000)] public async Task VerifyLoopChainIsDetected() { const string rootSubject = "CN=Root"; diff --git a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorTest.cs b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorTest.cs index a8da19854..52d6f2b17 100644 --- a/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorTest.cs +++ b/Tests/Opc.Ua.Core.Tests/Security/Certificates/CertificateValidatorTest.cs @@ -39,6 +39,8 @@ using System.Threading.Tasks; using NUnit.Framework; using Opc.Ua.Security.Certificates; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + #if NETCOREAPP2_1 || !ECC_SUPPORT using X509SignatureGenerator = Opc.Ua.Security.Certificates.X509SignatureGenerator; #endif diff --git a/Tests/Opc.Ua.Core.Tests/Stack/Client/ClientTests.cs b/Tests/Opc.Ua.Core.Tests/Stack/Client/ClientTests.cs index 21dbf4d15..4c11b8c7f 100644 --- a/Tests/Opc.Ua.Core.Tests/Stack/Client/ClientTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Stack/Client/ClientTests.cs @@ -34,6 +34,8 @@ using System.Xml; using NUnit.Framework; using Opc.Ua.Tests; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Stack.Client { diff --git a/Tests/Opc.Ua.Core.Tests/Stack/Schema/UANodeSetHelpersTests.cs b/Tests/Opc.Ua.Core.Tests/Stack/Schema/UANodeSetHelpersTests.cs index 58fd57ef8..07f7d29f9 100644 --- a/Tests/Opc.Ua.Core.Tests/Stack/Schema/UANodeSetHelpersTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Stack/Schema/UANodeSetHelpersTests.cs @@ -34,6 +34,8 @@ using System.Xml; using NUnit.Framework; using Opc.Ua.Tests; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Stack.Schema { diff --git a/Tests/Opc.Ua.Core.Tests/Stack/Server/ServerBaseTests.cs b/Tests/Opc.Ua.Core.Tests/Stack/Server/ServerBaseTests.cs index b3550d7b2..58db8773e 100644 --- a/Tests/Opc.Ua.Core.Tests/Stack/Server/ServerBaseTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Stack/Server/ServerBaseTests.cs @@ -30,6 +30,7 @@ using System; using System.Linq; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Core.Tests.Stack.Server { diff --git a/Tests/Opc.Ua.Core.Tests/Stack/State/NodeStateCollectionConcurrencyTests.cs b/Tests/Opc.Ua.Core.Tests/Stack/State/NodeStateCollectionConcurrencyTests.cs index 0867ef84d..6432ea36c 100644 --- a/Tests/Opc.Ua.Core.Tests/Stack/State/NodeStateCollectionConcurrencyTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Stack/State/NodeStateCollectionConcurrencyTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading.Tasks; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Core.Tests.Stack.State { diff --git a/Tests/Opc.Ua.Core.Tests/Stack/State/NodeStateHandlerConcurrencyTests.cs b/Tests/Opc.Ua.Core.Tests/Stack/State/NodeStateHandlerConcurrencyTests.cs index d7b618859..a66843626 100644 --- a/Tests/Opc.Ua.Core.Tests/Stack/State/NodeStateHandlerConcurrencyTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Stack/State/NodeStateHandlerConcurrencyTests.cs @@ -4,6 +4,8 @@ using System.Threading; using System.Threading.Tasks; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Stack.State { diff --git a/Tests/Opc.Ua.Core.Tests/Stack/State/NodeStateTests.cs b/Tests/Opc.Ua.Core.Tests/Stack/State/NodeStateTests.cs index f8343d578..22fd7b8a3 100644 --- a/Tests/Opc.Ua.Core.Tests/Stack/State/NodeStateTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Stack/State/NodeStateTests.cs @@ -31,6 +31,7 @@ using System.Linq; using System.Reflection; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Core.Tests.Stack.State { diff --git a/Tests/Opc.Ua.Core.Tests/Stack/Transport/MessageSocketTests.cs b/Tests/Opc.Ua.Core.Tests/Stack/Transport/MessageSocketTests.cs index 59e86e103..901a70f61 100644 --- a/Tests/Opc.Ua.Core.Tests/Stack/Transport/MessageSocketTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Stack/Transport/MessageSocketTests.cs @@ -7,6 +7,7 @@ using Moq; using NUnit.Framework; using Opc.Ua.Bindings; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Core.Tests.Stack.Transport { diff --git a/Tests/Opc.Ua.Core.Tests/Stack/Types/WriteValueTests.cs b/Tests/Opc.Ua.Core.Tests/Stack/Types/WriteValueTests.cs index 9f3ee64af..90f574f28 100644 --- a/Tests/Opc.Ua.Core.Tests/Stack/Types/WriteValueTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Stack/Types/WriteValueTests.cs @@ -31,6 +31,8 @@ using System.Linq; using NUnit.Framework; using Opc.Ua.Test; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Stack.Types { diff --git a/Tests/Opc.Ua.Core.Tests/Types/BuiltIn/BuiltInTests.cs b/Tests/Opc.Ua.Core.Tests/Types/BuiltIn/BuiltInTests.cs index e1d72ea93..28eaa9c60 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/BuiltIn/BuiltInTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/BuiltIn/BuiltInTests.cs @@ -32,6 +32,8 @@ using System.Linq; using NUnit.Framework; using Opc.Ua.Test; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Types.BuiltIn { diff --git a/Tests/Opc.Ua.Core.Tests/Types/BuiltIn/SessionLessServiceMessageTests.cs b/Tests/Opc.Ua.Core.Tests/Types/BuiltIn/SessionLessServiceMessageTests.cs index fd32f603d..774bf6b51 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/BuiltIn/SessionLessServiceMessageTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/BuiltIn/SessionLessServiceMessageTests.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using Newtonsoft.Json.Linq; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Core.Tests.Types.BuiltIn { diff --git a/Tests/Opc.Ua.Core.Tests/Types/ContentFilter/ContentFilterTests.cs b/Tests/Opc.Ua.Core.Tests/Types/ContentFilter/ContentFilterTests.cs index 1526c8548..23fa52fba 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/ContentFilter/ContentFilterTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/ContentFilter/ContentFilterTests.cs @@ -30,6 +30,7 @@ using System; using System.Collections.Generic; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Core.Tests.Types.ContentFilter { diff --git a/Tests/Opc.Ua.Core.Tests/Types/Encoders/BinaryEncoderBenchmarks.cs b/Tests/Opc.Ua.Core.Tests/Types/Encoders/BinaryEncoderBenchmarks.cs index fff30f452..706c3498d 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Encoders/BinaryEncoderBenchmarks.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Encoders/BinaryEncoderBenchmarks.cs @@ -33,6 +33,7 @@ using Microsoft.IO; using NUnit.Framework; using Opc.Ua.Bindings; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Core.Tests.Types.Encoders { diff --git a/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncodeableTests.cs b/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncodeableTests.cs index 9adbfdee2..1bd14d2b9 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncodeableTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncodeableTests.cs @@ -33,6 +33,8 @@ using System.Text; using System.Xml; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Types.Encoders { diff --git a/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncoderCommon.cs b/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncoderCommon.cs index 3ef4f09e1..a8e990fea 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncoderCommon.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncoderCommon.cs @@ -43,6 +43,8 @@ using NUnit.Framework; using Opc.Ua.Bindings; using Opc.Ua.Test; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Types.Encoders { diff --git a/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncoderTests.cs b/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncoderTests.cs index 94fd0518b..defd31f39 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncoderTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Encoders/EncoderTests.cs @@ -31,6 +31,8 @@ using System.IO; using System.Text; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Types.Encoders { diff --git a/Tests/Opc.Ua.Core.Tests/Types/Encoders/JsonEncoderBenchmarks.cs b/Tests/Opc.Ua.Core.Tests/Types/Encoders/JsonEncoderBenchmarks.cs index 2ac94acae..fafb04567 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Encoders/JsonEncoderBenchmarks.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Encoders/JsonEncoderBenchmarks.cs @@ -34,6 +34,8 @@ using Microsoft.IO; using NUnit.Framework; using Opc.Ua.Bindings; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Types.Encoders { diff --git a/Tests/Opc.Ua.Core.Tests/Types/Encoders/JsonEncoderEscapeStringBenchmarks.cs b/Tests/Opc.Ua.Core.Tests/Types/Encoders/JsonEncoderEscapeStringBenchmarks.cs index c1746fd4d..50da76327 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Encoders/JsonEncoderEscapeStringBenchmarks.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Encoders/JsonEncoderEscapeStringBenchmarks.cs @@ -37,6 +37,7 @@ using BenchmarkDotNet.Diagnosers; using Microsoft.IO; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Core.Tests.Types.Encoders { diff --git a/Tests/Opc.Ua.Core.Tests/Types/Encoders/JsonEncoderTests.cs b/Tests/Opc.Ua.Core.Tests/Types/Encoders/JsonEncoderTests.cs index 88288eee8..78ce518aa 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Encoders/JsonEncoderTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Encoders/JsonEncoderTests.cs @@ -37,6 +37,7 @@ using BenchmarkDotNet.Attributes; using Microsoft.IO; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; using Opc.Ua.Bindings; namespace Opc.Ua.Core.Tests.Types.Encoders diff --git a/Tests/Opc.Ua.Core.Tests/Types/Schemas/BinarySchemaWellKnownTests.cs b/Tests/Opc.Ua.Core.Tests/Types/Schemas/BinarySchemaWellKnownTests.cs index fd9e59fac..814b1e9af 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Schemas/BinarySchemaWellKnownTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Schemas/BinarySchemaWellKnownTests.cs @@ -31,6 +31,8 @@ using System.Threading.Tasks; using NUnit.Framework; using Opc.Ua.Schema.Binary; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Types.Schemas { diff --git a/Tests/Opc.Ua.Core.Tests/Types/Schemas/XmlSchemaWellKnownTests.cs b/Tests/Opc.Ua.Core.Tests/Types/Schemas/XmlSchemaWellKnownTests.cs index 4767785e5..211906d1d 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Schemas/XmlSchemaWellKnownTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Schemas/XmlSchemaWellKnownTests.cs @@ -37,6 +37,8 @@ using NUnit.Framework.Constraints; using Opc.Ua.Core.Tests.Stack.Schema; using Opc.Ua.Schema.Xml; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Types.Schemas { diff --git a/Tests/Opc.Ua.Core.Tests/Types/Utils/HiResClock.cs b/Tests/Opc.Ua.Core.Tests/Types/Utils/HiResClock.cs index 85bb00b21..342be1fc1 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Utils/HiResClock.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Utils/HiResClock.cs @@ -32,6 +32,8 @@ using System.Runtime.InteropServices; using BenchmarkDotNet.Attributes; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Types.UtilsTests { diff --git a/Tests/Opc.Ua.Core.Tests/Types/Utils/LogTests.cs b/Tests/Opc.Ua.Core.Tests/Types/Utils/LogTests.cs index 0801c8e0c..5acd597fe 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Utils/LogTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Utils/LogTests.cs @@ -32,6 +32,8 @@ using System.IO; using Microsoft.Extensions.Logging; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Types.LogTests { diff --git a/Tests/Opc.Ua.Core.Tests/Types/Utils/NumericRangeTests.cs b/Tests/Opc.Ua.Core.Tests/Types/Utils/NumericRangeTests.cs index a1f97d6fa..72dd07794 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Utils/NumericRangeTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Utils/NumericRangeTests.cs @@ -31,6 +31,8 @@ using System.Linq; using NUnit.Framework; using Opc.Ua.Test; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Types.NumericRange { diff --git a/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsIsEqualTests.cs b/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsIsEqualTests.cs index 92e5a7d7f..14339f59e 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsIsEqualTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsIsEqualTests.cs @@ -36,6 +36,8 @@ using System.Xml; using BenchmarkDotNet.Attributes; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Types.UtilsTests { diff --git a/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs b/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs index 2983299e2..617aff203 100644 --- a/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs +++ b/Tests/Opc.Ua.Core.Tests/Types/Utils/UtilsTests.cs @@ -36,6 +36,8 @@ using System.Text; using System.Xml; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Core.Tests.Types.UtilsTests { diff --git a/Tests/Opc.Ua.Gds.Tests/CertificateGroupTests.cs b/Tests/Opc.Ua.Gds.Tests/CertificateGroupTests.cs index f8dd7b6df..8c8d3375e 100644 --- a/Tests/Opc.Ua.Gds.Tests/CertificateGroupTests.cs +++ b/Tests/Opc.Ua.Gds.Tests/CertificateGroupTests.cs @@ -7,6 +7,8 @@ using NUnit.Framework; using Opc.Ua.Gds.Server; using Opc.Ua.Security.Certificates; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Gds.Tests { diff --git a/Tests/Opc.Ua.Gds.Tests/ClientTest.cs b/Tests/Opc.Ua.Gds.Tests/ClientTest.cs index 91dfbb67b..8ca574c94 100644 --- a/Tests/Opc.Ua.Gds.Tests/ClientTest.cs +++ b/Tests/Opc.Ua.Gds.Tests/ClientTest.cs @@ -36,6 +36,9 @@ using System.Threading; using System.Threading.Tasks; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + + namespace Opc.Ua.Gds.Tests { diff --git a/Tests/Opc.Ua.Gds.Tests/Opc.Ua.Gds.Tests.csproj b/Tests/Opc.Ua.Gds.Tests/Opc.Ua.Gds.Tests.csproj index 23344cdd9..a2efa135e 100644 --- a/Tests/Opc.Ua.Gds.Tests/Opc.Ua.Gds.Tests.csproj +++ b/Tests/Opc.Ua.Gds.Tests/Opc.Ua.Gds.Tests.csproj @@ -13,7 +13,7 @@ - + all diff --git a/Tests/Opc.Ua.Gds.Tests/PushTest.cs b/Tests/Opc.Ua.Gds.Tests/PushTest.cs index c0d61ca19..6eb9d99b7 100644 --- a/Tests/Opc.Ua.Gds.Tests/PushTest.cs +++ b/Tests/Opc.Ua.Gds.Tests/PushTest.cs @@ -41,6 +41,8 @@ using Opc.Ua.Security.Certificates; using Opc.Ua.Test; using OpcUa = Opc.Ua; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Gds.Tests { @@ -475,7 +477,7 @@ public void UpdateCertificateSelfSigned(string keyFormat) var keyFormats = m_pushClient.PushClient.GetSupportedKeyFormats(); if (!keyFormats.Contains(keyFormat)) { - Assert.Ignore("Push server doesn't support {0} key update", keyFormat); + Assert.Ignore($"Push server doesn't support {keyFormat} key update"); } X509Certificate2 newCert = CertificateFactory.CreateCertificate( @@ -497,7 +499,7 @@ public void UpdateCertificateSelfSigned(string keyFormat) } else { - Assert.Fail("Testing unsupported key format {0}.", keyFormat); + Assert.Fail($"Testing unsupported key format {keyFormat}."); } var success = m_pushClient.PushClient.UpdateCertificate( @@ -533,7 +535,7 @@ public void UpdateCertificateWithNewKeyPair(string keyFormat) var keyFormats = m_pushClient.PushClient.GetSupportedKeyFormats(); if (!keyFormats.Contains(keyFormat)) { - Assert.Ignore("Push server doesn't support {0} key update", keyFormat); + Assert.Ignore($"Push server doesn't support {keyFormat} key update"); } NodeId requestId = m_gdsClient.GDSClient.StartNewKeyPairRequest( diff --git a/Tests/Opc.Ua.Gds.Tests/X509TestUtils.cs b/Tests/Opc.Ua.Gds.Tests/X509TestUtils.cs index 56bc5ade9..e61ad47a1 100644 --- a/Tests/Opc.Ua.Gds.Tests/X509TestUtils.cs +++ b/Tests/Opc.Ua.Gds.Tests/X509TestUtils.cs @@ -32,6 +32,8 @@ using System.Security.Cryptography.X509Certificates; using NUnit.Framework; using Opc.Ua.Security.Certificates; +using Assert = NUnit.Framework.Legacy.ClassicAssert; + namespace Opc.Ua.Gds.Tests { diff --git a/Tests/Opc.Ua.PubSub.Tests/Configuration/PubSubConfiguratorTests.cs b/Tests/Opc.Ua.PubSub.Tests/Configuration/PubSubConfiguratorTests.cs index e19fd9f3e..19b6f41a7 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Configuration/PubSubConfiguratorTests.cs +++ b/Tests/Opc.Ua.PubSub.Tests/Configuration/PubSubConfiguratorTests.cs @@ -31,6 +31,7 @@ using System; using Opc.Ua.PubSub.Configuration; using System.IO; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.Configuration { diff --git a/Tests/Opc.Ua.PubSub.Tests/Configuration/PubSubStateMachineTests.StateChangeMethods.cs b/Tests/Opc.Ua.PubSub.Tests/Configuration/PubSubStateMachineTests.StateChangeMethods.cs index cd945fbf9..e95e6e5be 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Configuration/PubSubStateMachineTests.StateChangeMethods.cs +++ b/Tests/Opc.Ua.PubSub.Tests/Configuration/PubSubStateMachineTests.StateChangeMethods.cs @@ -30,6 +30,7 @@ using NUnit.Framework; using System; using Opc.Ua.PubSub.Configuration; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.Configuration { diff --git a/Tests/Opc.Ua.PubSub.Tests/Configuration/UaPubSubApplicationTests.cs b/Tests/Opc.Ua.PubSub.Tests/Configuration/UaPubSubApplicationTests.cs index a9da353ed..e5d5c177f 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Configuration/UaPubSubApplicationTests.cs +++ b/Tests/Opc.Ua.PubSub.Tests/Configuration/UaPubSubApplicationTests.cs @@ -32,6 +32,7 @@ using System.Linq; using NUnit.Framework; using Opc.Ua.PubSub.Configuration; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.Configuration { diff --git a/Tests/Opc.Ua.PubSub.Tests/Configuration/UaPubSubDataStoreTests.cs b/Tests/Opc.Ua.PubSub.Tests/Configuration/UaPubSubDataStoreTests.cs index a2e3b8190..260cc8fa6 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Configuration/UaPubSubDataStoreTests.cs +++ b/Tests/Opc.Ua.PubSub.Tests/Configuration/UaPubSubDataStoreTests.cs @@ -29,6 +29,7 @@ using System; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.Configuration { diff --git a/Tests/Opc.Ua.PubSub.Tests/Configuration/UaPublisherTests.cs b/Tests/Opc.Ua.PubSub.Tests/Configuration/UaPublisherTests.cs index aad156fd8..8b38c9d29 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Configuration/UaPublisherTests.cs +++ b/Tests/Opc.Ua.PubSub.Tests/Configuration/UaPublisherTests.cs @@ -33,6 +33,7 @@ using Moq; using NUnit.Framework; using System.Linq; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.Configuration { diff --git a/Tests/Opc.Ua.PubSub.Tests/Encoding/MqttJsonNetworkMessageTests.cs b/Tests/Opc.Ua.PubSub.Tests/Encoding/MqttJsonNetworkMessageTests.cs index 5349713bc..f35a4a4c1 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Encoding/MqttJsonNetworkMessageTests.cs +++ b/Tests/Opc.Ua.PubSub.Tests/Encoding/MqttJsonNetworkMessageTests.cs @@ -45,6 +45,7 @@ using Opc.Ua.PubSub.Encoding; using Opc.Ua.PubSub.PublishedData; using Opc.Ua.PubSub.Transport; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.Encoding { @@ -1553,7 +1554,7 @@ private void ValidateMetaDataEncoding(JsonNetworkMessage jsonNetworkMessage) MetaDataFailOptions failOptions = VerifyDataSetMetaDataEncoding(jsonNetworkMessage); if (failOptions != MetaDataFailOptions.Ok) { - Assert.Fail("The mandatory 'jsonNetworkMessage.{0}' field is wrong or missing from decoded message.", failOptions); + Assert.Fail($"The mandatory 'jsonNetworkMessage.{failOptions}' field is wrong or missing from decoded message."); } } @@ -1706,14 +1707,14 @@ private void ValidateDataEncoding(JsonNetworkMessage jsonNetworkMessage) { if ((NetworkMessageFailOptions)failOptions != NetworkMessageFailOptions.Ok) { - Assert.Fail("The mandatory 'jsonNetworkMessage.{0}' field is wrong or missing from decoded message.", failOptions); + Assert.Fail($"The mandatory 'jsonNetworkMessage.{failOptions}' field is wrong or missing from decoded message."); } } if (failOptions is DataSetMessageFailOptions) { if ((DataSetMessageFailOptions)failOptions != DataSetMessageFailOptions.Ok) { - Assert.Fail("The mandatory 'jsonDataSetMessage.{0}' field is wrong or missing from decoded message.", failOptions); + Assert.Fail($"The mandatory 'jsonDataSetMessage.{failOptions}' field is wrong or missing from decoded message."); } } } @@ -2098,12 +2099,12 @@ private object DecodeFieldData(IJsonDecoder jsonDecoder, FieldMetaData fieldMeta } else { - Assert.Warn("JsonDataSetMessage - Decoding ValueRank = {0} not supported yet !!!", fieldMetaData.ValueRank); + Assert.Warn($"JsonDataSetMessage - Decoding ValueRank = {fieldMetaData.ValueRank} not supported yet !!!"); } } catch (Exception ex) { - Assert.Warn("JsonDataSetMessage - Error reading element for RawData. {0}", ex.Message); + Assert.Warn($"JsonDataSetMessage - Error reading element for RawData. {ex.Message}"); return (StatusCodes.BadDecodingError); } } @@ -2179,7 +2180,7 @@ private object DecodeFieldByType(IJsonDecoder jsonDecoder, byte builtInType, str } catch (Exception) { - Assert.Warn("JsonDataSetMessage - Error decoding field {0}", fieldName); + Assert.Warn($"JsonDataSetMessage - Error decoding field {fieldName}"); } return null; diff --git a/Tests/Opc.Ua.PubSub.Tests/Encoding/MqttUadpNetworkMessageTests.cs b/Tests/Opc.Ua.PubSub.Tests/Encoding/MqttUadpNetworkMessageTests.cs index 969b24caf..dc07292d1 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Encoding/MqttUadpNetworkMessageTests.cs +++ b/Tests/Opc.Ua.PubSub.Tests/Encoding/MqttUadpNetworkMessageTests.cs @@ -37,6 +37,7 @@ using Opc.Ua.PubSub.Encoding; using Opc.Ua.PubSub.PublishedData; using Opc.Ua.PubSub.Transport; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.Encoding { diff --git a/Tests/Opc.Ua.PubSub.Tests/Encoding/UadpDataSetMessageTests.cs b/Tests/Opc.Ua.PubSub.Tests/Encoding/UadpDataSetMessageTests.cs index da48270b6..edf0a2f2a 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Encoding/UadpDataSetMessageTests.cs +++ b/Tests/Opc.Ua.PubSub.Tests/Encoding/UadpDataSetMessageTests.cs @@ -33,6 +33,7 @@ using System.Linq; using System.IO; using Opc.Ua.PubSub.Encoding; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.Encoding { diff --git a/Tests/Opc.Ua.PubSub.Tests/Encoding/UadpNetworkMessageTests.cs b/Tests/Opc.Ua.PubSub.Tests/Encoding/UadpNetworkMessageTests.cs index f982a88ca..fd5467276 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Encoding/UadpNetworkMessageTests.cs +++ b/Tests/Opc.Ua.PubSub.Tests/Encoding/UadpNetworkMessageTests.cs @@ -35,6 +35,7 @@ using System.IO; using DataSet = Opc.Ua.PubSub.PublishedData.DataSet; using Opc.Ua.PubSub.Encoding; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.Encoding { diff --git a/Tests/Opc.Ua.PubSub.Tests/Opc.Ua.PubSub.Tests.csproj b/Tests/Opc.Ua.PubSub.Tests/Opc.Ua.PubSub.Tests.csproj index 576804c4f..65a5f6375 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Opc.Ua.PubSub.Tests.csproj +++ b/Tests/Opc.Ua.PubSub.Tests/Opc.Ua.PubSub.Tests.csproj @@ -9,7 +9,7 @@ - + all diff --git a/Tests/Opc.Ua.PubSub.Tests/PublishedData/DataCollectorTests.cs b/Tests/Opc.Ua.PubSub.Tests/PublishedData/DataCollectorTests.cs index 7966bc608..cf642a3f4 100644 --- a/Tests/Opc.Ua.PubSub.Tests/PublishedData/DataCollectorTests.cs +++ b/Tests/Opc.Ua.PubSub.Tests/PublishedData/DataCollectorTests.cs @@ -33,6 +33,7 @@ using NUnit.Framework; using Opc.Ua.PubSub.Configuration; using Opc.Ua.PubSub.PublishedData; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.PublishedData { diff --git a/Tests/Opc.Ua.PubSub.Tests/PublishedData/WriterGroupPublishedStateTests.cs b/Tests/Opc.Ua.PubSub.Tests/PublishedData/WriterGroupPublishedStateTests.cs index bf99839ef..aa6b6166d 100644 --- a/Tests/Opc.Ua.PubSub.Tests/PublishedData/WriterGroupPublishedStateTests.cs +++ b/Tests/Opc.Ua.PubSub.Tests/PublishedData/WriterGroupPublishedStateTests.cs @@ -35,6 +35,7 @@ using Opc.Ua.PubSub.Tests.Encoding; using Opc.Ua.PubSub.PublishedData; using System.Reflection; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.PublishedData { diff --git a/Tests/Opc.Ua.PubSub.Tests/Transport/MqttPubSubConnectionTests.cs b/Tests/Opc.Ua.PubSub.Tests/Transport/MqttPubSubConnectionTests.cs index 1373a1e50..8cd5d271e 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Transport/MqttPubSubConnectionTests.cs +++ b/Tests/Opc.Ua.PubSub.Tests/Transport/MqttPubSubConnectionTests.cs @@ -38,6 +38,7 @@ using Opc.Ua.PubSub.Tests.Encoding; using System.Collections.Generic; using Opc.Ua.PubSub.PublishedData; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.Transport { diff --git a/Tests/Opc.Ua.PubSub.Tests/Transport/UdpClientCreatorTests.cs b/Tests/Opc.Ua.PubSub.Tests/Transport/UdpClientCreatorTests.cs index 140e53315..08f79ac04 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Transport/UdpClientCreatorTests.cs +++ b/Tests/Opc.Ua.PubSub.Tests/Transport/UdpClientCreatorTests.cs @@ -36,6 +36,7 @@ using System.Runtime.InteropServices; using NUnit.Framework; using Opc.Ua.PubSub.Transport; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.Transport { diff --git a/Tests/Opc.Ua.PubSub.Tests/Transport/UdpPubSubConnectionTests.Publisher.cs b/Tests/Opc.Ua.PubSub.Tests/Transport/UdpPubSubConnectionTests.Publisher.cs index 4e29ccd76..c958ed4f5 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Transport/UdpPubSubConnectionTests.Publisher.cs +++ b/Tests/Opc.Ua.PubSub.Tests/Transport/UdpPubSubConnectionTests.Publisher.cs @@ -36,6 +36,7 @@ using System.Net; using System.Net.Sockets; using System.Threading; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.Transport { diff --git a/Tests/Opc.Ua.PubSub.Tests/Transport/UdpPubSubConnectionTests.Subscriber.cs b/Tests/Opc.Ua.PubSub.Tests/Transport/UdpPubSubConnectionTests.Subscriber.cs index b04bf2895..95fe7b66c 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Transport/UdpPubSubConnectionTests.Subscriber.cs +++ b/Tests/Opc.Ua.PubSub.Tests/Transport/UdpPubSubConnectionTests.Subscriber.cs @@ -37,6 +37,7 @@ using Opc.Ua.PubSub.Configuration; using Opc.Ua.PubSub.Encoding; using Opc.Ua.PubSub.Transport; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.Transport { diff --git a/Tests/Opc.Ua.PubSub.Tests/Transport/UdpPubSubConnectionTests.cs b/Tests/Opc.Ua.PubSub.Tests/Transport/UdpPubSubConnectionTests.cs index cd83bc280..e4c1a4f78 100644 --- a/Tests/Opc.Ua.PubSub.Tests/Transport/UdpPubSubConnectionTests.cs +++ b/Tests/Opc.Ua.PubSub.Tests/Transport/UdpPubSubConnectionTests.cs @@ -38,6 +38,7 @@ using NUnit.Framework; using Opc.Ua.PubSub.Encoding; using Opc.Ua.PubSub.Transport; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.PubSub.Tests.Transport { diff --git a/Tests/Opc.Ua.Security.Certificates.Tests/CRLTests.cs b/Tests/Opc.Ua.Security.Certificates.Tests/CRLTests.cs index 7d1a5660b..274500179 100644 --- a/Tests/Opc.Ua.Security.Certificates.Tests/CRLTests.cs +++ b/Tests/Opc.Ua.Security.Certificates.Tests/CRLTests.cs @@ -37,6 +37,7 @@ using System.Text; using NUnit.Framework; using Opc.Ua.Tests; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Security.Certificates.Tests { diff --git a/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForECDsa.cs b/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForECDsa.cs index f89f83a07..2c2d24ab7 100644 --- a/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForECDsa.cs +++ b/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForECDsa.cs @@ -34,6 +34,7 @@ using System.Security.Cryptography.X509Certificates; using NUnit.Framework; using Opc.Ua.Tests; + using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Security.Certificates.Tests { @@ -94,6 +95,7 @@ public void VerifyOneSelfSignedAppCertForAll() .SetECCurve(eCCurveHash.Curve) .CreateForECDsa()) { + Assert.NotNull(cert); WriteCertificate(cert, $"Default cert with ECDsa {eCCurveHash.Curve.Oid.FriendlyName} {eCCurveHash.HashAlgorithmName} signature."); Assert.AreEqual(eCCurveHash.HashAlgorithmName, Oids.GetHashAlgorithmName(cert.SignatureAlgorithm.Value)); diff --git a/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForRSA.cs b/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForRSA.cs index fd7d4bc81..e9563031e 100644 --- a/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForRSA.cs +++ b/Tests/Opc.Ua.Security.Certificates.Tests/CertificateTestsForRSA.cs @@ -35,6 +35,7 @@ using System.Security.Cryptography.X509Certificates; using NUnit.Framework; using Opc.Ua.Tests; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Security.Certificates.Tests { diff --git a/Tests/Opc.Ua.Security.Certificates.Tests/ExtensionTests.cs b/Tests/Opc.Ua.Security.Certificates.Tests/ExtensionTests.cs index 63324e149..5078a0264 100644 --- a/Tests/Opc.Ua.Security.Certificates.Tests/ExtensionTests.cs +++ b/Tests/Opc.Ua.Security.Certificates.Tests/ExtensionTests.cs @@ -33,6 +33,7 @@ using System.Security.Cryptography.X509Certificates; using NUnit.Framework; using Opc.Ua.Tests; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Security.Certificates.Tests { diff --git a/Tests/Opc.Ua.Security.Certificates.Tests/Opc.Ua.Security.Certificates.Tests.csproj b/Tests/Opc.Ua.Security.Certificates.Tests/Opc.Ua.Security.Certificates.Tests.csproj index a37c580d7..c2daf5e7d 100644 --- a/Tests/Opc.Ua.Security.Certificates.Tests/Opc.Ua.Security.Certificates.Tests.csproj +++ b/Tests/Opc.Ua.Security.Certificates.Tests/Opc.Ua.Security.Certificates.Tests.csproj @@ -24,7 +24,7 @@ - + all diff --git a/Tests/Opc.Ua.Security.Certificates.Tests/TestUtils.cs b/Tests/Opc.Ua.Security.Certificates.Tests/TestUtils.cs index db57ef42a..9483d7593 100644 --- a/Tests/Opc.Ua.Security.Certificates.Tests/TestUtils.cs +++ b/Tests/Opc.Ua.Security.Certificates.Tests/TestUtils.cs @@ -35,6 +35,7 @@ using System.Security.Cryptography.X509Certificates; using NUnit.Framework; using Opc.Ua.Security.Certificates; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Tests { diff --git a/Tests/Opc.Ua.Server.Tests/CommonTestWorkers.cs b/Tests/Opc.Ua.Server.Tests/CommonTestWorkers.cs index 3f373e8de..cbe52e0e6 100644 --- a/Tests/Opc.Ua.Server.Tests/CommonTestWorkers.cs +++ b/Tests/Opc.Ua.Server.Tests/CommonTestWorkers.cs @@ -31,6 +31,7 @@ using System.Linq; using System.Threading; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Server.Tests { diff --git a/Tests/Opc.Ua.Server.Tests/LinqUserDatabaseTests.cs b/Tests/Opc.Ua.Server.Tests/LinqUserDatabaseTests.cs index fa7a552ea..b6f44ceb6 100644 --- a/Tests/Opc.Ua.Server.Tests/LinqUserDatabaseTests.cs +++ b/Tests/Opc.Ua.Server.Tests/LinqUserDatabaseTests.cs @@ -3,6 +3,7 @@ using NUnit.Framework; using Opc.Ua.Server; using Opc.Ua.Server.UserDatabase; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Server.Tests { diff --git a/Tests/Opc.Ua.Server.Tests/MasterNodeManagerTests.cs b/Tests/Opc.Ua.Server.Tests/MasterNodeManagerTests.cs index 3841c0bfa..0ec01d4c8 100644 --- a/Tests/Opc.Ua.Server.Tests/MasterNodeManagerTests.cs +++ b/Tests/Opc.Ua.Server.Tests/MasterNodeManagerTests.cs @@ -31,6 +31,7 @@ using System.Threading.Tasks; using Moq; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Server.Tests { diff --git a/Tests/Opc.Ua.Server.Tests/Opc.Ua.Server.Tests.csproj b/Tests/Opc.Ua.Server.Tests/Opc.Ua.Server.Tests.csproj index 3d32fcc30..74af9b15a 100644 --- a/Tests/Opc.Ua.Server.Tests/Opc.Ua.Server.Tests.csproj +++ b/Tests/Opc.Ua.Server.Tests/Opc.Ua.Server.Tests.csproj @@ -10,7 +10,7 @@ - + all diff --git a/Tests/Opc.Ua.Server.Tests/ReferenceServerTest.cs b/Tests/Opc.Ua.Server.Tests/ReferenceServerTest.cs index 1458ee392..7bd41fd1f 100644 --- a/Tests/Opc.Ua.Server.Tests/ReferenceServerTest.cs +++ b/Tests/Opc.Ua.Server.Tests/ReferenceServerTest.cs @@ -35,6 +35,7 @@ using NUnit.Framework; using Opc.Ua.Test; using Quickstarts.ReferenceServer; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Server.Tests { diff --git a/Tests/Opc.Ua.Server.Tests/ServerFixture.cs b/Tests/Opc.Ua.Server.Tests/ServerFixture.cs index 69278d086..798679120 100644 --- a/Tests/Opc.Ua.Server.Tests/ServerFixture.cs +++ b/Tests/Opc.Ua.Server.Tests/ServerFixture.cs @@ -86,6 +86,7 @@ public async Task LoadConfiguration(string pkiRoot = null) "uri:opcfoundation.org:" + typeof(T).Name) .SetMaxByteStringLength(4 * 1024 * 1024) .SetMaxArrayLength(1024 * 1024) + .SetChannelLifetime(30000) .AsServer( new string[] { endpointUrl @@ -131,6 +132,7 @@ public async Task LoadConfiguration(string pkiRoot = null) serverConfig.SetMaxMessageQueueSize(20); serverConfig.SetDiagnosticsEnabled(true); serverConfig.SetAuditingEnabled(true); + serverConfig.SetMaxChannelCount(10); if (ReverseConnectTimeout != 0) { diff --git a/Tests/Opc.Ua.Server.Tests/ServerStartupTests.cs b/Tests/Opc.Ua.Server.Tests/ServerStartupTests.cs index 995686126..0f712a611 100644 --- a/Tests/Opc.Ua.Server.Tests/ServerStartupTests.cs +++ b/Tests/Opc.Ua.Server.Tests/ServerStartupTests.cs @@ -29,6 +29,7 @@ using System.Threading.Tasks; using NUnit.Framework; +using Assert = NUnit.Framework.Legacy.ClassicAssert; namespace Opc.Ua.Server.Tests { diff --git a/targets.props b/targets.props index f13e72980..84793d752 100644 --- a/targets.props +++ b/targets.props @@ -128,13 +128,13 @@ latest - netcoreapp3.1;net48 - netcoreapp3.1 - net48;netcoreapp3.1 + net48 + net48 + net48 net48;netstandard2.1 net48;netstandard2.0;netstandard2.1 net48;netstandard2.1 - net48;netcoreapp3.1 + net48