diff --git a/Lawo.EmberPlusSharpTest/S101/CommunicationTestBase.cs b/Lawo.EmberPlusSharpTest/S101/CommunicationTestBase.cs index 5f5d99f9..81779471 100644 --- a/Lawo.EmberPlusSharpTest/S101/CommunicationTestBase.cs +++ b/Lawo.EmberPlusSharpTest/S101/CommunicationTestBase.cs @@ -9,6 +9,7 @@ namespace Lawo.EmberPlusSharp.S101 using System; using System.Diagnostics.CodeAnalysis; using System.IO; + using System.Linq; using System.Net; using System.Net.Sockets; using System.Reflection; @@ -26,6 +27,8 @@ public abstract class CommunicationTestBase : TestBase { private static readonly EmberData EmberDataCommandField = new EmberData(0x01, 0x0A, 0x02); private static readonly S101Message EmberDataMessageField = new S101Message(0x00, EmberDataCommandField); + private static readonly S101Message KeepAliveRequestMessageField = new S101Message(0x00, new KeepAliveRequest()); + private static readonly S101Message KeepAliveResponseMessageField = new S101Message(0x00, new KeepAliveResponse()); //////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -47,6 +50,18 @@ protected static S101Message EmberDataMessage get { return EmberDataMessageField; } } + /// Gets a message with an command. + protected static S101Message KeepAliveRequestMessage + { + get { return KeepAliveRequestMessageField; } + } + + /// Gets a message with an command. + protected static S101Message KeepAliveResponseMessage + { + get { return KeepAliveResponseMessageField; } + } + /// Uses to simulate a provider communicating with the /// object passed to . /// The type whose namespace is used to scope @@ -232,6 +247,19 @@ protected static async Task MonitorConnection( await waitForConnectionLost; } + /// Gets a random byte that is guaranteed to not be equal to any of the elements in + /// . + protected byte GetRandomByteExcept(params byte[] exceptions) + { + byte result; + + while (exceptions.Contains(result = (byte)this.Random.Next(byte.MinValue, byte.MaxValue + 1))) + { + } + + return result; + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////// private static Task Read( diff --git a/Lawo.EmberPlusSharpTest/S101/S101ClientTest.cs b/Lawo.EmberPlusSharpTest/S101/S101ClientTest.cs index 601a1200..b52c4ef4 100644 --- a/Lawo.EmberPlusSharpTest/S101/S101ClientTest.cs +++ b/Lawo.EmberPlusSharpTest/S101/S101ClientTest.cs @@ -238,18 +238,5 @@ public void VersionTest() null, null)); } - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - private byte GetRandomByteExcept(params byte[] exceptions) - { - byte result; - - while (exceptions.Contains(result = (byte)this.Random.Next(byte.MinValue, byte.MaxValue + 1))) - { - } - - return result; - } } } diff --git a/Lawo.EmberPlusSharpTest/S101/S101WriterTest.cs b/Lawo.EmberPlusSharpTest/S101/S101WriterTest.cs index 0505e300..52232583 100644 --- a/Lawo.EmberPlusSharpTest/S101/S101WriterTest.cs +++ b/Lawo.EmberPlusSharpTest/S101/S101WriterTest.cs @@ -54,24 +54,27 @@ public void OutOfFrameByteTest() AsyncPump.Run( async () => { + var first = GetRandomByteExcept(0xFE); + var second = GetRandomByteExcept(0xFE); + + var prefix = new[] { GetRandomByteExcept() }; + var third = GetRandomByteExcept(0xFE); + var postfix = new[] { GetRandomByteExcept() }; + using (var asyncStream = new MemoryStream()) { var writer = new S101Writer(asyncStream.WriteAsync); try { - await writer.WriteMessageAsync( - new S101Message(0x00, new KeepAliveRequest()), CancellationToken.None); - await writer.WriteOutOfFrameByte((byte)this.Random.Next(0xFE), CancellationToken.None); - await writer.WriteMessageAsync( - new S101Message(0x00, new KeepAliveResponse()), CancellationToken.None); + await writer.WriteOutOfFrameByte(first, CancellationToken.None); + await writer.WriteMessageAsync(KeepAliveRequestMessage, CancellationToken.None); + await writer.WriteOutOfFrameByte(second, CancellationToken.None); using (var encodingStream = await writer.WriteMessageAsync(EmberDataMessage, CancellationToken.None)) { - var prefix = new byte[] { 0x42 }; - var postfix = new byte[] { 0x43 }; await encodingStream.WriteAsync(prefix, 0, prefix.Length, CancellationToken.None); - await writer.WriteOutOfFrameByte(0xEE, CancellationToken.None); + await writer.WriteOutOfFrameByte(third, CancellationToken.None); await encodingStream.WriteAsync(postfix, 0, postfix.Length, CancellationToken.None); await encodingStream.DisposeAsync(CancellationToken.None); } @@ -81,9 +84,30 @@ await writer.WriteMessageAsync( await writer.DisposeAsync(CancellationToken.None); } - var stringBytes = - asyncStream.ToArray().Select(b => b.ToString("X2", CultureInfo.InvariantCulture)); - var result = string.Join(", ", stringBytes).ToUpperInvariant(); + asyncStream.Position = 0; + var reader = new S101Reader(asyncStream.ReadAsync); + var firstTask = WaitForOutOfFrameByte(reader); + Assert.IsTrue(await reader.ReadAsync(CancellationToken.None)); + Assert.AreEqual(0x00, reader.Message.Slot); + Assert.IsInstanceOfType(reader.Message.Command, typeof(KeepAliveRequest)); + Assert.AreEqual(first, await firstTask); + var secondTask = WaitForOutOfFrameByte(reader); + Assert.IsTrue(await reader.ReadAsync(CancellationToken.None)); + Assert.AreEqual(0x00, reader.Message.Slot); + Assert.IsInstanceOfType(reader.Message.Command, typeof(EmberData)); + Assert.AreEqual(second, await secondTask); + var thirdTask = WaitForOutOfFrameByte(reader); + + using (var payloadStream = new MemoryStream()) + { + await reader.Payload.CopyToAsync(payloadStream); + var payload = payloadStream.ToArray(); + Assert.AreEqual(2, payload.Length); + Assert.AreEqual(prefix.Single(), payload[0]); + Assert.AreEqual(postfix.Single(), payload[1]); + } + + Assert.AreEqual(third, await thirdTask); } }); } @@ -190,21 +214,36 @@ await AssertThrowAsync( () => stream.Position = 0, () => stream.Seek(0, SeekOrigin.Begin)); - await AssertThrowAsync( - () => writer.WriteMessageAsync(new S101Message(0x00, new KeepAliveRequest()), CancellationToken.None)); + await AssertThrowAsync(() => writer.WriteMessageAsync( + new S101Message(0x00, new KeepAliveRequest()), CancellationToken.None)); await stream.DisposeAsync(CancellationToken.None); await AssertThrowAsync( () => stream.WriteAsync(new byte[] { 2 }, 0, 1, CancellationToken.None)); } await writer.DisposeAsync(CancellationToken.None); - await AssertThrowAsync( - () => writer.WriteMessageAsync(new S101Message(0x00, new KeepAliveRequest()), CancellationToken.None)); + await AssertThrowAsync(() => writer.WriteMessageAsync( + new S101Message(0x00, new KeepAliveRequest()), CancellationToken.None)); }); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////// + private Task WaitForOutOfFrameByte(S101Reader reader) + { + var resultSource = new TaskCompletionSource(); + EventHandler handler = null; + + handler = (s, e) => + { + reader.OutOfFrameByteReceived -= handler; + resultSource.SetResult(e.Value); + }; + + reader.OutOfFrameByteReceived += handler; + return resultSource.Task; + } + private static async Task Encode(S101Message message, byte[] payload = null) { using (var asyncStream = new MemoryStream())