From 09c8b18d3dc7bdc172d59a7eff01bf4905eb3c9c Mon Sep 17 00:00:00 2001 From: Serge Camille Date: Tue, 18 Aug 2020 23:41:07 +0200 Subject: [PATCH] Adjust ReadFixed implementation somewhat. Exceeding the length of the buffer was already an error before. Change the tests by replacing the memory buffer with a Fake stream giving 1 byte at a time. --- S7.Net.UnitTest/ProtocolTests.cs | 31 ++---------- S7.Net.UnitTest/StreamTests.cs | 82 ++++++++++++++++++++++++++++++++ S7.Net/StreamExtensions.cs | 12 ++--- 3 files changed, 90 insertions(+), 35 deletions(-) create mode 100644 S7.Net.UnitTest/StreamTests.cs diff --git a/S7.Net.UnitTest/ProtocolTests.cs b/S7.Net.UnitTest/ProtocolTests.cs index 0a2312a..fdb68d9 100644 --- a/S7.Net.UnitTest/ProtocolTests.cs +++ b/S7.Net.UnitTest/ProtocolTests.cs @@ -34,32 +34,6 @@ namespace S7.Net.UnitTest var t = TPKT.Read(m); } - [TestMethod] - public async Task TPKT_ReadDelayedAsync() - { - var fullMessage = ProtocolUnitTest.StringToByteArray("0300002902f0803203000000010002001400000401ff0400807710000100000103000000033f8ccccd"); - var m = new MemoryStream(); - m.Write(fullMessage, 0, 2); - var tcs = new TaskCompletionSource(); - tcs.Task.ContinueWith(x => m.Write(fullMessage, 2, fullMessage.Length - 2)); - var t = TPKT.ReadAsync(m); - tcs.TrySetResult(true); - await t; - } - - [TestMethod] - public void TPKT_ReadDelayed() - { - var fullMessage = ProtocolUnitTest.StringToByteArray("0300002902f0803203000000010002001400000401ff0400807710000100000103000000033f8ccccd"); - var m = new MemoryStream(); - m.Write(fullMessage, 0, 2); - var tcs = new TaskCompletionSource(); - tcs.Task.ContinueWith(x => m.Write(fullMessage, 2, fullMessage.Length - 2)); - - Task.Delay(TimeSpan.FromSeconds(0.01)).ContinueWith(x => tcs.TrySetResult(true)); - var t = TPKT.Read(m); - tcs.TrySetResult(true); - } [TestMethod] [ExpectedException(typeof(TPKTInvalidException))] @@ -67,7 +41,7 @@ namespace S7.Net.UnitTest { var m = new MemoryStream(StringToByteArray("0300002902f0803203000000010002001400000401ff040080")); var t = await TPKT.ReadAsync(m); - } + } [TestMethod] public void COTP_ReadTSDU() @@ -81,7 +55,7 @@ namespace S7.Net.UnitTest Assert.IsTrue(expected.SequenceEqual(t)); } - private static byte[] StringToByteArray(string hex) + public static byte[] StringToByteArray(string hex) { return Enumerable.Range(0, hex.Length) .Where(x => x % 2 == 0) @@ -89,4 +63,5 @@ namespace S7.Net.UnitTest .ToArray(); } } + } diff --git a/S7.Net.UnitTest/StreamTests.cs b/S7.Net.UnitTest/StreamTests.cs new file mode 100644 index 0000000..1d33e21 --- /dev/null +++ b/S7.Net.UnitTest/StreamTests.cs @@ -0,0 +1,82 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace S7.Net.UnitTest +{ + /// + /// Test stream which only gives 1 byte per read. + /// + class TestStream1BytePerRead : Stream + { + public TestStream1BytePerRead(byte[] data) + { + Data = data; + } + public override bool CanRead => _position < Data.Length; + + public override bool CanSeek => throw new NotImplementedException(); + + public override bool CanWrite => throw new NotImplementedException(); + + public override long Length => throw new NotImplementedException(); + + public override long Position { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + public byte[] Data { get; } + + public override void Flush() + { + throw new NotImplementedException(); + } + + int _position = 0; + public override int Read(byte[] buffer, int offset, int count) + { + buffer[offset] = Data[_position]; + ++_position; + return 1; + } + + public override long Seek(long offset, SeekOrigin origin) + { + throw new NotImplementedException(); + } + + public override void SetLength(long value) + { + throw new NotImplementedException(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotImplementedException(); + } + } + + [TestClass] + public class StreamTests + { + + [TestMethod] + public async Task TPKT_ReadRestrictedStreamAsync() + { + var fullMessage = ProtocolUnitTest.StringToByteArray("0300002902f0803203000000010002001400000401ff0400807710000100000103000000033f8ccccd"); + var m = new TestStream1BytePerRead(fullMessage); + var t = await TPKT.ReadAsync(m); + Assert.AreEqual(fullMessage.Length, t.Length); + Assert.AreEqual(fullMessage.Last(), t.Data.Last()); + } + + [TestMethod] + public void TPKT_ReadRestrictedStream() + { + var fullMessage = ProtocolUnitTest.StringToByteArray("0300002902f0803203000000010002001400000401ff0400807710000100000103000000033f8ccccd"); + var m = new TestStream1BytePerRead(fullMessage); + var t = TPKT.Read(m); + Assert.AreEqual(fullMessage.Length, t.Length); + Assert.AreEqual(fullMessage.Last(), t.Data.Last()); + } + } +} diff --git a/S7.Net/StreamExtensions.cs b/S7.Net/StreamExtensions.cs index 663597e..dc8db73 100644 --- a/S7.Net/StreamExtensions.cs +++ b/S7.Net/StreamExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Threading.Tasks; @@ -19,12 +19,11 @@ namespace S7.Net /// returns the amount of read bytes public static int ReadFixed(this Stream stream, byte[] buffer, int offset, int count) { - int read = offset; + int read = 0; int received; - count = Math.Min(count, buffer.Length - offset); do { - received = stream.Read(buffer, read, count - read); + received = stream.Read(buffer, offset + read, count - read); read += received; } while (read < count && received > 0); @@ -42,12 +41,11 @@ namespace S7.Net /// returns the amount of read bytes public static async Task ReadFixedAsync(this Stream stream, byte[] buffer, int offset, int count) { - int read = offset; + int read = 0; int received; - count = Math.Min(count, buffer.Length - offset); do { - received = await stream.ReadAsync(buffer, read, count - read); + received = await stream.ReadAsync(buffer, offset + read, count - read); read += received; } while (read < count && received > 0);