Moved some more settings to the connection interface
This commit is contained in:
@@ -25,6 +25,21 @@ namespace AMWD.Protocols.Modbus.Common.Contracts
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
TimeSpan IdleTimeout { get; set; }
|
TimeSpan IdleTimeout { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the maximum time until the connect attempt is given up.
|
||||||
|
/// </summary>
|
||||||
|
TimeSpan ConnectTimeout { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the receive time out value of the connection.
|
||||||
|
/// </summary>
|
||||||
|
TimeSpan ReadTimeout { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the send time out value of the connection.
|
||||||
|
/// </summary>
|
||||||
|
TimeSpan WriteTimeout { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Invokes a Modbus request.
|
/// Invokes a Modbus request.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AMWD.Protocols.Modbus.Tcp.Utils
|
namespace AMWD.Protocols.Modbus.Common.Utils
|
||||||
{
|
{
|
||||||
internal class RequestQueueItem
|
internal class RequestQueueItem
|
||||||
{
|
{
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
<Compile Include="../AMWD.Protocols.Modbus.Common/Extensions/ArrayExtensions.cs" Link="Extensions/ArrayExtensions.cs" />
|
<Compile Include="../AMWD.Protocols.Modbus.Common/Extensions/ArrayExtensions.cs" Link="Extensions/ArrayExtensions.cs" />
|
||||||
<Compile Include="../AMWD.Protocols.Modbus.Common/Extensions/ReaderWriterLockSlimExtensions.cs" Link="Extensions/ReaderWriterLockSlimExtensions.cs" />
|
<Compile Include="../AMWD.Protocols.Modbus.Common/Extensions/ReaderWriterLockSlimExtensions.cs" Link="Extensions/ReaderWriterLockSlimExtensions.cs" />
|
||||||
<Compile Include="../AMWD.Protocols.Modbus.Common/Utils/AsyncQueue.cs" Link="Utils/AsyncQueue.cs" />
|
<Compile Include="../AMWD.Protocols.Modbus.Common/Utils/AsyncQueue.cs" Link="Utils/AsyncQueue.cs" />
|
||||||
|
<Compile Include="../AMWD.Protocols.Modbus.Common/Utils/RequestQueueItem.cs" Link="Utils/RequestQueueItem.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ namespace AMWD.Protocols.Modbus.Tcp
|
|||||||
{ }
|
{ }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ModbusClientBase"/> class with a specific <see cref="IModbusConnection"/>.
|
/// Initializes a new instance of the <see cref="ModbusTcpClient"/> class with a specific <see cref="IModbusConnection"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="connection">The <see cref="IModbusConnection"/> responsible for invoking the requests.</param>
|
/// <param name="connection">The <see cref="IModbusConnection"/> responsible for invoking the requests.</param>
|
||||||
/// <param name="disposeConnection">
|
/// <param name="disposeConnection">
|
||||||
@@ -43,6 +43,34 @@ namespace AMWD.Protocols.Modbus.Tcp
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override IModbusProtocol Protocol { get; set; }
|
public override IModbusProtocol Protocol { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IModbusConnection.IdleTimeout"/>
|
||||||
|
public TimeSpan IdleTimeout
|
||||||
|
{
|
||||||
|
get => connection.IdleTimeout;
|
||||||
|
set => connection.IdleTimeout = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IModbusConnection.ConnectTimeout"/>
|
||||||
|
public TimeSpan ConnectTimeout
|
||||||
|
{
|
||||||
|
get => connection.ConnectTimeout;
|
||||||
|
set => connection.ConnectTimeout = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IModbusConnection.ReadTimeout"/>
|
||||||
|
public TimeSpan ReadTimeout
|
||||||
|
{
|
||||||
|
get => connection.ReadTimeout;
|
||||||
|
set => connection.ReadTimeout = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IModbusConnection.WriteTimeout"/>
|
||||||
|
public TimeSpan WriteTimeout
|
||||||
|
{
|
||||||
|
get => connection.WriteTimeout;
|
||||||
|
set => connection.WriteTimeout = value;
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="ModbusTcpConnection.Hostname"/>
|
/// <inheritdoc cref="ModbusTcpConnection.Hostname"/>
|
||||||
public string Hostname
|
public string Hostname
|
||||||
{
|
{
|
||||||
@@ -76,73 +104,5 @@ namespace AMWD.Protocols.Modbus.Tcp
|
|||||||
tcpConnection.Port = value;
|
tcpConnection.Port = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="ModbusTcpConnection.ReadTimeout"/>
|
|
||||||
public TimeSpan ReadTimeout
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (connection is ModbusTcpConnection tcpConnection)
|
|
||||||
return tcpConnection.ReadTimeout;
|
|
||||||
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (connection is ModbusTcpConnection tcpConnection)
|
|
||||||
tcpConnection.ReadTimeout = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="ModbusTcpConnection.WriteTimeout"/>
|
|
||||||
public TimeSpan WriteTimeout
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (connection is ModbusTcpConnection tcpConnection)
|
|
||||||
return tcpConnection.WriteTimeout;
|
|
||||||
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (connection is ModbusTcpConnection tcpConnection)
|
|
||||||
tcpConnection.WriteTimeout = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="ModbusTcpConnection.ConnectTimeout"/>
|
|
||||||
public TimeSpan ReconnectTimeout
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (connection is ModbusTcpConnection tcpConnection)
|
|
||||||
return tcpConnection.ConnectTimeout;
|
|
||||||
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (connection is ModbusTcpConnection tcpConnection)
|
|
||||||
tcpConnection.ConnectTimeout = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="ModbusTcpConnection.IdleTimeout"/>
|
|
||||||
public TimeSpan IdleTimeout
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (connection is ModbusTcpConnection tcpConnection)
|
|
||||||
return tcpConnection.IdleTimeout;
|
|
||||||
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (connection is ModbusTcpConnection tcpConnection)
|
|
||||||
tcpConnection.IdleTimeout = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AMWD.Protocols.Modbus.Common.Contracts;
|
using AMWD.Protocols.Modbus.Common.Contracts;
|
||||||
using AMWD.Protocols.Modbus.Common.Protocols;
|
using AMWD.Protocols.Modbus.Common.Protocols;
|
||||||
|
using AMWD.Protocols.Modbus.Common.Utils;
|
||||||
using AMWD.Protocols.Modbus.Tcp.Utils;
|
using AMWD.Protocols.Modbus.Tcp.Utils;
|
||||||
|
|
||||||
namespace AMWD.Protocols.Modbus.Tcp
|
namespace AMWD.Protocols.Modbus.Tcp
|
||||||
@@ -26,7 +27,7 @@ namespace AMWD.Protocols.Modbus.Tcp
|
|||||||
private readonly CancellationTokenSource _disposeCts = new();
|
private readonly CancellationTokenSource _disposeCts = new();
|
||||||
|
|
||||||
private readonly SemaphoreSlim _clientLock = new(1, 1);
|
private readonly SemaphoreSlim _clientLock = new(1, 1);
|
||||||
private readonly TcpClientWrapper _client = new();
|
private readonly TcpClientWrapper _tcpClient = new();
|
||||||
private readonly Timer _idleTimer;
|
private readonly Timer _idleTimer;
|
||||||
|
|
||||||
private readonly Task _processingTask;
|
private readonly Task _processingTask;
|
||||||
@@ -51,6 +52,23 @@ namespace AMWD.Protocols.Modbus.Tcp
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public virtual TimeSpan IdleTimeout { get; set; } = TimeSpan.FromSeconds(6);
|
public virtual TimeSpan IdleTimeout { get; set; } = TimeSpan.FromSeconds(6);
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public virtual TimeSpan ConnectTimeout { get; set; } = TimeSpan.MaxValue;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public virtual TimeSpan ReadTimeout
|
||||||
|
{
|
||||||
|
get => TimeSpan.FromMilliseconds(_tcpClient.ReceiveTimeout);
|
||||||
|
set => _tcpClient.ReceiveTimeout = (int)value.TotalMilliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public virtual TimeSpan WriteTimeout
|
||||||
|
{
|
||||||
|
get => TimeSpan.FromMilliseconds(_tcpClient.SendTimeout);
|
||||||
|
set => _tcpClient.SendTimeout = (int)value.TotalMilliseconds;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The DNS name of the remote host to which the connection is intended to.
|
/// The DNS name of the remote host to which the connection is intended to.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -81,32 +99,11 @@ namespace AMWD.Protocols.Modbus.Tcp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the receive time out value of the connection.
|
|
||||||
/// </summary>
|
|
||||||
public virtual TimeSpan ReadTimeout
|
|
||||||
{
|
|
||||||
get => TimeSpan.FromMilliseconds(_client.ReceiveTimeout);
|
|
||||||
set => _client.ReceiveTimeout = (int)value.TotalMilliseconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the send time out value of the connection.
|
|
||||||
/// </summary>
|
|
||||||
public virtual TimeSpan WriteTimeout
|
|
||||||
{
|
|
||||||
get => TimeSpan.FromMilliseconds(_client.SendTimeout);
|
|
||||||
set => _client.SendTimeout = (int)value.TotalMilliseconds;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the maximum time until the connect attempt is given up.
|
|
||||||
/// </summary>
|
|
||||||
public virtual TimeSpan ConnectTimeout { get; set; } = TimeSpan.MaxValue;
|
|
||||||
|
|
||||||
#endregion Properties
|
#endregion Properties
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <summary>
|
||||||
|
/// Releases all managed and unmanaged resources used by the <see cref="ModbusTcpConnection"/>.
|
||||||
|
/// </summary>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
if (_isDisposed)
|
if (_isDisposed)
|
||||||
@@ -127,7 +124,7 @@ namespace AMWD.Protocols.Modbus.Tcp
|
|||||||
|
|
||||||
OnIdleTimer(null);
|
OnIdleTimer(null);
|
||||||
|
|
||||||
_client.Dispose();
|
_tcpClient.Dispose();
|
||||||
_clientLock.Dispose();
|
_clientLock.Dispose();
|
||||||
|
|
||||||
while (_requestQueue.TryDequeue(out var item))
|
while (_requestQueue.TryDequeue(out var item))
|
||||||
@@ -204,7 +201,7 @@ namespace AMWD.Protocols.Modbus.Tcp
|
|||||||
// Ensure connection is up
|
// Ensure connection is up
|
||||||
await AssertConnection(linkedCts.Token).ConfigureAwait(false);
|
await AssertConnection(linkedCts.Token).ConfigureAwait(false);
|
||||||
|
|
||||||
var stream = _client.GetStream();
|
var stream = _tcpClient.GetStream();
|
||||||
await stream.FlushAsync(linkedCts.Token).ConfigureAwait(false);
|
await stream.FlushAsync(linkedCts.Token).ConfigureAwait(false);
|
||||||
|
|
||||||
#if NET6_0_OR_GREATER
|
#if NET6_0_OR_GREATER
|
||||||
@@ -270,7 +267,7 @@ namespace AMWD.Protocols.Modbus.Tcp
|
|||||||
// Has to be called within _clientLock!
|
// Has to be called within _clientLock!
|
||||||
private async Task AssertConnection(CancellationToken cancellationToken)
|
private async Task AssertConnection(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (_client.Connected)
|
if (_tcpClient.Connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int delay = 1;
|
int delay = 1;
|
||||||
@@ -287,17 +284,17 @@ namespace AMWD.Protocols.Modbus.Tcp
|
|||||||
{
|
{
|
||||||
foreach (var ipAddress in ipAddresses)
|
foreach (var ipAddress in ipAddresses)
|
||||||
{
|
{
|
||||||
_client.Close();
|
_tcpClient.Close();
|
||||||
|
|
||||||
#if NET6_0_OR_GREATER
|
#if NET6_0_OR_GREATER
|
||||||
using var connectTask = _client.ConnectAsync(ipAddress, Port, cancellationToken);
|
using var connectTask = _tcpClient.ConnectAsync(ipAddress, Port, cancellationToken);
|
||||||
#else
|
#else
|
||||||
using var connectTask = _client.ConnectAsync(ipAddress, Port);
|
using var connectTask = _tcpClient.ConnectAsync(ipAddress, Port);
|
||||||
#endif
|
#endif
|
||||||
if (await Task.WhenAny(connectTask, Task.Delay(ReadTimeout, cancellationToken)) == connectTask)
|
if (await Task.WhenAny(connectTask, Task.Delay(ReadTimeout, cancellationToken)) == connectTask)
|
||||||
{
|
{
|
||||||
await connectTask;
|
await connectTask;
|
||||||
if (_client.Connected)
|
if (_tcpClient.Connected)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -327,10 +324,10 @@ namespace AMWD.Protocols.Modbus.Tcp
|
|||||||
_clientLock.Wait(_disposeCts.Token);
|
_clientLock.Wait(_disposeCts.Token);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!_client.Connected)
|
if (!_tcpClient.Connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_client.Close();
|
_tcpClient.Close();
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using AMWD.Protocols.Modbus.Common.Contracts;
|
using AMWD.Protocols.Modbus.Tcp;
|
||||||
using AMWD.Protocols.Modbus.Tcp;
|
|
||||||
using Moq;
|
using Moq;
|
||||||
|
|
||||||
namespace AMWD.Protocols.Modbus.Tests.Tcp
|
namespace AMWD.Protocols.Modbus.Tests.Tcp
|
||||||
@@ -14,13 +13,20 @@ namespace AMWD.Protocols.Modbus.Tests.Tcp
|
|||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
_genericConnectionMock = new Mock<IModbusConnection>();
|
_genericConnectionMock = new Mock<IModbusConnection>();
|
||||||
|
_genericConnectionMock.Setup(c => c.IdleTimeout).Returns(TimeSpan.FromSeconds(40));
|
||||||
|
_genericConnectionMock.Setup(c => c.ConnectTimeout).Returns(TimeSpan.FromSeconds(30));
|
||||||
|
_genericConnectionMock.Setup(c => c.ReadTimeout).Returns(TimeSpan.FromSeconds(20));
|
||||||
|
_genericConnectionMock.Setup(c => c.WriteTimeout).Returns(TimeSpan.FromSeconds(10));
|
||||||
|
|
||||||
_tcpConnectionMock = new Mock<ModbusTcpConnection>();
|
_tcpConnectionMock = new Mock<ModbusTcpConnection>();
|
||||||
|
|
||||||
|
_tcpConnectionMock.Setup(c => c.IdleTimeout).Returns(TimeSpan.FromSeconds(10));
|
||||||
|
_tcpConnectionMock.Setup(c => c.ConnectTimeout).Returns(TimeSpan.FromSeconds(20));
|
||||||
|
_tcpConnectionMock.Setup(c => c.ReadTimeout).Returns(TimeSpan.FromSeconds(30));
|
||||||
|
_tcpConnectionMock.Setup(c => c.WriteTimeout).Returns(TimeSpan.FromSeconds(40));
|
||||||
|
|
||||||
_tcpConnectionMock.Setup(c => c.Hostname).Returns("127.0.0.1");
|
_tcpConnectionMock.Setup(c => c.Hostname).Returns("127.0.0.1");
|
||||||
_tcpConnectionMock.Setup(c => c.Port).Returns(502);
|
_tcpConnectionMock.Setup(c => c.Port).Returns(502);
|
||||||
_tcpConnectionMock.Setup(c => c.ReadTimeout).Returns(TimeSpan.FromSeconds(10));
|
|
||||||
_tcpConnectionMock.Setup(c => c.WriteTimeout).Returns(TimeSpan.FromSeconds(20));
|
|
||||||
_tcpConnectionMock.Setup(c => c.ConnectTimeout).Returns(TimeSpan.FromSeconds(30));
|
|
||||||
_tcpConnectionMock.Setup(c => c.IdleTimeout).Returns(TimeSpan.FromSeconds(40));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
@@ -32,18 +38,10 @@ namespace AMWD.Protocols.Modbus.Tests.Tcp
|
|||||||
// Act
|
// Act
|
||||||
string hostname = client.Hostname;
|
string hostname = client.Hostname;
|
||||||
int port = client.Port;
|
int port = client.Port;
|
||||||
TimeSpan readTimeout = client.ReadTimeout;
|
|
||||||
TimeSpan writeTimeout = client.WriteTimeout;
|
|
||||||
TimeSpan reconnectTimeout = client.ReconnectTimeout;
|
|
||||||
TimeSpan idleTimeout = client.IdleTimeout;
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.IsNull(hostname);
|
Assert.IsNull(hostname);
|
||||||
Assert.AreEqual(0, port);
|
Assert.AreEqual(0, port);
|
||||||
Assert.AreEqual(TimeSpan.Zero, readTimeout);
|
|
||||||
Assert.AreEqual(TimeSpan.Zero, writeTimeout);
|
|
||||||
Assert.AreEqual(TimeSpan.Zero, reconnectTimeout);
|
|
||||||
Assert.AreEqual(TimeSpan.Zero, idleTimeout);
|
|
||||||
|
|
||||||
_genericConnectionMock.VerifyNoOtherCalls();
|
_genericConnectionMock.VerifyNoOtherCalls();
|
||||||
}
|
}
|
||||||
@@ -57,17 +55,59 @@ namespace AMWD.Protocols.Modbus.Tests.Tcp
|
|||||||
// Act
|
// Act
|
||||||
client.Hostname = "localhost";
|
client.Hostname = "localhost";
|
||||||
client.Port = 205;
|
client.Port = 205;
|
||||||
client.ReadTimeout = TimeSpan.FromSeconds(123);
|
|
||||||
client.WriteTimeout = TimeSpan.FromSeconds(456);
|
|
||||||
client.ReconnectTimeout = TimeSpan.FromSeconds(789);
|
|
||||||
client.IdleTimeout = TimeSpan.FromSeconds(321);
|
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
_genericConnectionMock.VerifyNoOtherCalls();
|
_genericConnectionMock.VerifyNoOtherCalls();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void ShouldReturnValuesForTcpConnection()
|
public void ShouldReturnValuesForGenericConnection()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var client = new ModbusTcpClient(_genericConnectionMock.Object);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var idleTimeout = client.IdleTimeout;
|
||||||
|
var connectTimeout = client.ConnectTimeout;
|
||||||
|
var readTimeout = client.ReadTimeout;
|
||||||
|
var writeTimeout = client.WriteTimeout;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.AreEqual(TimeSpan.FromSeconds(40), idleTimeout);
|
||||||
|
Assert.AreEqual(TimeSpan.FromSeconds(30), connectTimeout);
|
||||||
|
Assert.AreEqual(TimeSpan.FromSeconds(20), readTimeout);
|
||||||
|
Assert.AreEqual(TimeSpan.FromSeconds(10), writeTimeout);
|
||||||
|
|
||||||
|
_genericConnectionMock.VerifyGet(c => c.IdleTimeout, Times.Once);
|
||||||
|
_genericConnectionMock.VerifyGet(c => c.ConnectTimeout, Times.Once);
|
||||||
|
_genericConnectionMock.VerifyGet(c => c.ReadTimeout, Times.Once);
|
||||||
|
_genericConnectionMock.VerifyGet(c => c.WriteTimeout, Times.Once);
|
||||||
|
_genericConnectionMock.VerifyNoOtherCalls();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ShouldSetValuesForGenericConnection()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var client = new ModbusTcpClient(_genericConnectionMock.Object);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
client.IdleTimeout = TimeSpan.FromSeconds(10);
|
||||||
|
client.ConnectTimeout = TimeSpan.FromSeconds(20);
|
||||||
|
client.ReadTimeout = TimeSpan.FromSeconds(30);
|
||||||
|
client.WriteTimeout = TimeSpan.FromSeconds(40);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
_genericConnectionMock.VerifySet(c => c.IdleTimeout = TimeSpan.FromSeconds(10), Times.Once);
|
||||||
|
_genericConnectionMock.VerifySet(c => c.ConnectTimeout = TimeSpan.FromSeconds(20), Times.Once);
|
||||||
|
_genericConnectionMock.VerifySet(c => c.ReadTimeout = TimeSpan.FromSeconds(30), Times.Once);
|
||||||
|
_genericConnectionMock.VerifySet(c => c.WriteTimeout = TimeSpan.FromSeconds(40), Times.Once);
|
||||||
|
|
||||||
|
_genericConnectionMock.VerifyNoOtherCalls();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ShouldGetValuesForTcpConnection()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var client = new ModbusTcpClient(_tcpConnectionMock.Object);
|
var client = new ModbusTcpClient(_tcpConnectionMock.Object);
|
||||||
@@ -75,25 +115,26 @@ namespace AMWD.Protocols.Modbus.Tests.Tcp
|
|||||||
// Act
|
// Act
|
||||||
string hostname = client.Hostname;
|
string hostname = client.Hostname;
|
||||||
int port = client.Port;
|
int port = client.Port;
|
||||||
TimeSpan readTimeout = client.ReadTimeout;
|
var idleTimeout = client.IdleTimeout;
|
||||||
TimeSpan writeTimeout = client.WriteTimeout;
|
var connectTimeout = client.ConnectTimeout;
|
||||||
TimeSpan reconnectTimeout = client.ReconnectTimeout;
|
var readTimeout = client.ReadTimeout;
|
||||||
TimeSpan keepAliveInterval = client.IdleTimeout;
|
var writeTimeout = client.WriteTimeout;
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
Assert.AreEqual("127.0.0.1", hostname);
|
Assert.AreEqual("127.0.0.1", hostname);
|
||||||
Assert.AreEqual(502, port);
|
Assert.AreEqual(502, port);
|
||||||
Assert.AreEqual(10, readTimeout.TotalSeconds);
|
Assert.AreEqual(TimeSpan.FromSeconds(10), idleTimeout);
|
||||||
Assert.AreEqual(20, writeTimeout.TotalSeconds);
|
Assert.AreEqual(TimeSpan.FromSeconds(20), connectTimeout);
|
||||||
Assert.AreEqual(30, reconnectTimeout.TotalSeconds);
|
Assert.AreEqual(TimeSpan.FromSeconds(30), readTimeout);
|
||||||
Assert.AreEqual(40, keepAliveInterval.TotalSeconds);
|
Assert.AreEqual(TimeSpan.FromSeconds(40), writeTimeout);
|
||||||
|
|
||||||
_tcpConnectionMock.VerifyGet(c => c.Hostname, Times.Once);
|
_tcpConnectionMock.VerifyGet(c => c.Hostname, Times.Once);
|
||||||
_tcpConnectionMock.VerifyGet(c => c.Port, Times.Once);
|
_tcpConnectionMock.VerifyGet(c => c.Port, Times.Once);
|
||||||
|
_tcpConnectionMock.VerifyGet(c => c.IdleTimeout, Times.Once);
|
||||||
|
_tcpConnectionMock.VerifyGet(c => c.ConnectTimeout, Times.Once);
|
||||||
_tcpConnectionMock.VerifyGet(c => c.ReadTimeout, Times.Once);
|
_tcpConnectionMock.VerifyGet(c => c.ReadTimeout, Times.Once);
|
||||||
_tcpConnectionMock.VerifyGet(c => c.WriteTimeout, Times.Once);
|
_tcpConnectionMock.VerifyGet(c => c.WriteTimeout, Times.Once);
|
||||||
_tcpConnectionMock.VerifyGet(c => c.ConnectTimeout, Times.Once);
|
|
||||||
_tcpConnectionMock.VerifyGet(c => c.IdleTimeout, Times.Once);
|
|
||||||
_tcpConnectionMock.VerifyNoOtherCalls();
|
_tcpConnectionMock.VerifyNoOtherCalls();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,18 +147,19 @@ namespace AMWD.Protocols.Modbus.Tests.Tcp
|
|||||||
// Act
|
// Act
|
||||||
client.Hostname = "localhost";
|
client.Hostname = "localhost";
|
||||||
client.Port = 205;
|
client.Port = 205;
|
||||||
client.ReadTimeout = TimeSpan.FromSeconds(123);
|
client.IdleTimeout = TimeSpan.FromSeconds(40);
|
||||||
client.WriteTimeout = TimeSpan.FromSeconds(456);
|
client.ConnectTimeout = TimeSpan.FromSeconds(30);
|
||||||
client.ReconnectTimeout = TimeSpan.FromSeconds(789);
|
client.ReadTimeout = TimeSpan.FromSeconds(20);
|
||||||
client.IdleTimeout = TimeSpan.FromSeconds(321);
|
client.WriteTimeout = TimeSpan.FromSeconds(10);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
_tcpConnectionMock.VerifySet(c => c.Hostname = "localhost", Times.Once);
|
_tcpConnectionMock.VerifySet(c => c.Hostname = "localhost", Times.Once);
|
||||||
_tcpConnectionMock.VerifySet(c => c.Port = 205, Times.Once);
|
_tcpConnectionMock.VerifySet(c => c.Port = 205, Times.Once);
|
||||||
_tcpConnectionMock.VerifySet(c => c.ReadTimeout = TimeSpan.FromSeconds(123), Times.Once);
|
_tcpConnectionMock.VerifySet(c => c.IdleTimeout = TimeSpan.FromSeconds(40), Times.Once);
|
||||||
_tcpConnectionMock.VerifySet(c => c.WriteTimeout = TimeSpan.FromSeconds(456), Times.Once);
|
_tcpConnectionMock.VerifySet(c => c.ConnectTimeout = TimeSpan.FromSeconds(30), Times.Once);
|
||||||
_tcpConnectionMock.VerifySet(c => c.ConnectTimeout = TimeSpan.FromSeconds(789), Times.Once);
|
_tcpConnectionMock.VerifySet(c => c.ReadTimeout = TimeSpan.FromSeconds(20), Times.Once);
|
||||||
_tcpConnectionMock.VerifySet(c => c.IdleTimeout = TimeSpan.FromSeconds(321), Times.Once);
|
_tcpConnectionMock.VerifySet(c => c.WriteTimeout = TimeSpan.FromSeconds(10), Times.Once);
|
||||||
|
|
||||||
_tcpConnectionMock.VerifyNoOtherCalls();
|
_tcpConnectionMock.VerifyNoOtherCalls();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using System.Net;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using AMWD.Protocols.Modbus.Common.Contracts;
|
|
||||||
using AMWD.Protocols.Modbus.Tcp;
|
using AMWD.Protocols.Modbus.Tcp;
|
||||||
using AMWD.Protocols.Modbus.Tcp.Utils;
|
using AMWD.Protocols.Modbus.Tcp.Utils;
|
||||||
using Moq;
|
using Moq;
|
||||||
@@ -528,18 +527,12 @@ namespace AMWD.Protocols.Modbus.Tests.Tcp
|
|||||||
Port = 502
|
Port = 502
|
||||||
};
|
};
|
||||||
|
|
||||||
// Replace real TCP client with mock
|
// Replace real connection with mock
|
||||||
var clientField = connection.GetType().GetField("_client", BindingFlags.NonPublic | BindingFlags.Instance);
|
var connectionField = connection.GetType().GetField("_tcpClient", BindingFlags.NonPublic | BindingFlags.Instance);
|
||||||
(clientField.GetValue(connection) as TcpClientWrapper)?.Dispose();
|
(connectionField.GetValue(connection) as TcpClientWrapper)?.Dispose();
|
||||||
clientField.SetValue(connection, _tcpClientMock.Object);
|
connectionField.SetValue(connection, _tcpClientMock.Object);
|
||||||
|
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ClearInvocations()
|
|
||||||
{
|
|
||||||
_networkStreamMock.Invocations.Clear();
|
|
||||||
_tcpClientMock.Invocations.Clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user