Skip to content

Commit

Permalink
test: Add CommunicationSequence
Browse files Browse the repository at this point in the history
  • Loading branch information
mycroes committed Jul 31, 2023
1 parent 088cd0a commit 714ac62
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 0 deletions.
7 changes: 7 additions & 0 deletions S7.Net.UnitTest/Framework/IsExternalInit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using System.ComponentModel;

namespace System.Runtime.CompilerServices
{
[EditorBrowsable(EditorBrowsableState.Never)]
internal record IsExternalInit;
}
82 changes: 82 additions & 0 deletions S7.Net.UnitTest/Infrastructure/CommunicationSequence.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;

namespace S7.Net.UnitTest;

internal class CommunicationSequence : IEnumerable<RequestResponsePair>
{
private readonly List<RequestResponsePair> _requestResponsePairs = new List<RequestResponsePair>();

public CommunicationSequence()
{

}

public void Add(string requestPattern, string responsePattern)
{
_requestResponsePairs.Add(new RequestResponsePair(requestPattern, responsePattern));
}

public IEnumerator<RequestResponsePair> GetEnumerator()
{
return _requestResponsePairs.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

public Task Serve(out int port)
{
var socket = CreateBoundListenSocket(out port);
socket.Listen(0);

async Task Impl()
{
await Task.Yield();
var socketIn = socket.Accept();

var buffer = ArrayPool<byte>.Shared.Rent(1024);
try
{
foreach (var pair in _requestResponsePairs)
{
var bytesReceived = socketIn.Receive(buffer, SocketFlags.None);

var received = buffer.Take(bytesReceived).ToArray();
Console.WriteLine($"=> {BitConverter.ToString(received)}");

var response = Responder.Respond(pair, received);

Console.WriteLine($"<= {BitConverter.ToString(response)}");
socketIn.Send(response);
}
}
finally
{
ArrayPool<byte>.Shared.Return(buffer);
}

socketIn.Close();
}

return Impl();
}

private static Socket CreateBoundListenSocket(out int port)
{
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
var endpoint = new IPEndPoint(IPAddress.Loopback, 0);

socket.Bind(endpoint);

var localEndpoint = (IPEndPoint)socket.LocalEndPoint!;
port = localEndpoint.Port;

return socket;
}
}
3 changes: 3 additions & 0 deletions S7.Net.UnitTest/Infrastructure/RequestResponsePair.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace S7.Net.UnitTest;

internal record RequestResponsePair(string RequestPattern, string ResponsePattern);
80 changes: 80 additions & 0 deletions S7.Net.UnitTest/Infrastructure/Responder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;

namespace S7.Net.UnitTest;

internal static class Responder
{
private const string Comment = "//";
private static char[] Space = " ".ToCharArray();

public static byte[] Respond(RequestResponsePair pair, byte[] request)
{
var offset = 0;
var matches = new Dictionary<string, byte>();
var res = new List<byte>();
using var requestReader = new StringReader(pair.RequestPattern);

string line;
while ((line = requestReader.ReadLine()) != null)
{
var tokens = line.Split(Space, StringSplitOptions.RemoveEmptyEntries);
foreach (var token in tokens)
{
if (token.StartsWith(Comment)) break;

if (offset >= request.Length)
{
throw new Exception("Request pattern has more data than request.");
}

var received = request[offset];

if (token.Length == 2 && byte.TryParse(token, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var value))
{
// Number, exact match
if (value != received)
{
throw new Exception($"Incorrect data at offset {offset}. Expected {value:X2}, received {received:X2}.");
}
}
else
{
matches[token] = received;
}

offset++;
}
}

if (offset != request.Length) throw new Exception("Request contained more data than request pattern.");

using var responseReader = new StringReader(pair.ResponsePattern);
while ((line = responseReader.ReadLine()) != null)
{
var tokens = line.Split(Space, StringSplitOptions.RemoveEmptyEntries);
foreach (var token in tokens)
{
if (token.StartsWith(Comment)) break;

if (token.Length == 2 && byte.TryParse(token, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var value))
{
res.Add(value);
}
else
{
if (!matches.TryGetValue(token, out var match))
{
throw new Exception($"Unmatched token '{token}' in response.");
}

res.Add(match);
}
}
}

return res.ToArray();
}
}
1 change: 1 addition & 0 deletions S7.Net.UnitTest/S7.Net.UnitTest.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
</PropertyGroup>

<PropertyGroup>
<LangVersion>latest</LangVersion>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Properties\S7.Net.snk</AssemblyOriginatorKeyFile>
<IsPackable>false</IsPackable>
Expand Down

0 comments on commit 714ac62

Please sign in to comment.