diff --git a/X10D.Tests/src/IO/StreamTests.ReadDecimal.cs b/X10D.Tests/src/IO/StreamTests.ReadDecimal.cs new file mode 100644 index 0000000..0c65320 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.ReadDecimal.cs @@ -0,0 +1,73 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + public void ReadDecimal_ShouldThrowArgumentException_GivenNonReadableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.ReadDecimal()); + Assert.ThrowsException(() => stream.ReadDecimal(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadDecimal(Endianness.BigEndian)); + } + + [TestMethod] + public void ReadDecimal_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.ReadDecimal()); + Assert.ThrowsException(() => stream.ReadDecimal(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadDecimal(Endianness.BigEndian)); + } + + [TestMethod] + public void ReadDecimal_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.ReadDecimal((Endianness)(-1))); + } + + [TestMethod] + public void ReadDecimal_ShouldReadBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] + { + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x68 + }; + stream.Write(bytes); + stream.Position = 0; + + const decimal expected = 420.0m; + decimal actual = stream.ReadDecimal(Endianness.BigEndian); + + Assert.AreEqual(16, stream.Position); + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ReadDecimal_ShouldWriteLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] + { + 0x68, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 + }; + stream.Write(bytes); + stream.Position = 0; + + const decimal expected = 420.0m; + decimal actual = stream.ReadDecimal(Endianness.LittleEndian); + + Assert.AreEqual(16, stream.Position); + Assert.AreEqual(expected, actual); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.ReadDouble.cs b/X10D.Tests/src/IO/StreamTests.ReadDouble.cs new file mode 100644 index 0000000..352df60 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.ReadDouble.cs @@ -0,0 +1,67 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + public void ReadDouble_ShouldThrowArgumentException_GivenNonReadableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.ReadDouble()); + Assert.ThrowsException(() => stream.ReadDouble(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadDouble(Endianness.BigEndian)); + } + + [TestMethod] + public void ReadDouble_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.ReadDouble()); + Assert.ThrowsException(() => stream.ReadDouble(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadDouble(Endianness.BigEndian)); + } + + [TestMethod] + public void ReadDouble_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.ReadDouble((Endianness)(-1))); + } + + [TestMethod] + public void ReadDouble_ShouldReadBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0x40, 0x7A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}; + stream.Write(bytes); + stream.Position = 0; + + const double expected = 420.0; + double actual = stream.ReadDouble(Endianness.BigEndian); + + Assert.AreEqual(8, stream.Position); + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ReadDouble_ShouldWriteLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7A, 0x40}; + stream.Write(bytes); + stream.Position = 0; + + const double expected = 420.0; + double actual = stream.ReadDouble(Endianness.LittleEndian); + + Assert.AreEqual(8, stream.Position); + Assert.AreEqual(expected, actual); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.ReadInt16.cs b/X10D.Tests/src/IO/StreamTests.ReadInt16.cs new file mode 100644 index 0000000..b41c82a --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.ReadInt16.cs @@ -0,0 +1,67 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + public void ReadInt16_ShouldThrowArgumentException_GivenNonReadableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.ReadInt16()); + Assert.ThrowsException(() => stream.ReadInt16(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadInt16(Endianness.BigEndian)); + } + + [TestMethod] + public void ReadInt16_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.ReadInt16()); + Assert.ThrowsException(() => stream.ReadInt16(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadInt16(Endianness.BigEndian)); + } + + [TestMethod] + public void ReadInt16_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.ReadInt16((Endianness)(-1))); + } + + [TestMethod] + public void ReadInt16_ShouldReadBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0x01, 0xA4}; + stream.Write(bytes); + stream.Position = 0; + + const short expected = 420; + short actual = stream.ReadInt16(Endianness.BigEndian); + + Assert.AreEqual(2, stream.Position); + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ReadInt16_ShouldReadLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0xA4, 0x01}; + stream.Write(bytes); + stream.Position = 0; + + const short expected = 420; + short actual = stream.ReadInt16(Endianness.LittleEndian); + + Assert.AreEqual(2, stream.Position); + Assert.AreEqual(expected, actual); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.ReadInt32.cs b/X10D.Tests/src/IO/StreamTests.ReadInt32.cs new file mode 100644 index 0000000..60442fe --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.ReadInt32.cs @@ -0,0 +1,67 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + public void ReadInt32_ShouldThrowArgumentException_GivenNonReadableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.ReadInt32()); + Assert.ThrowsException(() => stream.ReadInt32(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadInt32(Endianness.BigEndian)); + } + + [TestMethod] + public void ReadInt32_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.ReadInt32()); + Assert.ThrowsException(() => stream.ReadInt32(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadInt32(Endianness.BigEndian)); + } + + [TestMethod] + public void ReadInt32_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.ReadInt32((Endianness)(-1))); + } + + [TestMethod] + public void ReadInt32_ShouldReadBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0x00, 0x00, 0x01, 0xA4}; + stream.Write(bytes); + stream.Position = 0; + + const int expected = 420; + int actual = stream.ReadInt32(Endianness.BigEndian); + + Assert.AreEqual(4, stream.Position); + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ReadInt32_ShouldReadLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00}; + stream.Write(bytes); + stream.Position = 0; + + const int expected = 420; + int actual = stream.ReadInt32(Endianness.LittleEndian); + + Assert.AreEqual(4, stream.Position); + Assert.AreEqual(expected, actual); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.ReadInt64.cs b/X10D.Tests/src/IO/StreamTests.ReadInt64.cs new file mode 100644 index 0000000..23554b1 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.ReadInt64.cs @@ -0,0 +1,67 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + public void ReadInt64_ShouldThrowArgumentException_GivenNonReadableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.ReadInt64()); + Assert.ThrowsException(() => stream.ReadInt64(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadInt64(Endianness.BigEndian)); + } + + [TestMethod] + public void ReadInt64_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.ReadInt64()); + Assert.ThrowsException(() => stream.ReadInt64(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadInt64(Endianness.BigEndian)); + } + + [TestMethod] + public void ReadInt64_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.ReadInt64((Endianness)(-1))); + } + + [TestMethod] + public void ReadInt64_ShouldReadBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA4}; + stream.Write(bytes); + stream.Position = 0; + + const long expected = 420; + long actual = stream.ReadInt64(Endianness.BigEndian); + + Assert.AreEqual(8, stream.Position); + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ReadInt64_ShouldWriteLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + stream.Write(bytes); + stream.Position = 0; + + const long expected = 420; + long actual = stream.ReadInt64(Endianness.LittleEndian); + + Assert.AreEqual(8, stream.Position); + Assert.AreEqual(expected, actual); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.ReadSingle.cs b/X10D.Tests/src/IO/StreamTests.ReadSingle.cs new file mode 100644 index 0000000..35976c5 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.ReadSingle.cs @@ -0,0 +1,67 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + public void ReadSingle_ShouldThrowArgumentException_GivenNonReadableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.ReadSingle()); + Assert.ThrowsException(() => stream.ReadSingle(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadSingle(Endianness.BigEndian)); + } + + [TestMethod] + public void ReadSingle_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.ReadSingle()); + Assert.ThrowsException(() => stream.ReadSingle(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadSingle(Endianness.BigEndian)); + } + + [TestMethod] + public void ReadSingle_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.ReadSingle((Endianness)(-1))); + } + + [TestMethod] + public void ReadSingle_ShouldReadBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0x43, 0xD2, 0x00, 0x00}; + stream.Write(bytes); + stream.Position = 0; + + const float expected = 420.0f; + float actual = stream.ReadSingle(Endianness.BigEndian); + + Assert.AreEqual(4, stream.Position); + Assert.AreEqual(expected, actual); + } + + [TestMethod] + public void ReadSingle_ShouldReadLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0x00, 0x00, 0xD2, 0x43}; + stream.Write(bytes); + stream.Position = 0; + + const float expected = 420.0f; + float actual = stream.ReadSingle(Endianness.LittleEndian); + + Assert.AreEqual(4, stream.Position); + Assert.AreEqual(expected, actual); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.ReadUInt16.cs b/X10D.Tests/src/IO/StreamTests.ReadUInt16.cs new file mode 100644 index 0000000..b28c3e7 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.ReadUInt16.cs @@ -0,0 +1,72 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt16_ShouldThrowArgumentException_GivenNonReadableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.ReadUInt16()); + Assert.ThrowsException(() => stream.ReadUInt16(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadUInt16(Endianness.BigEndian)); + } + + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt16_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.ReadUInt16()); + Assert.ThrowsException(() => stream.ReadUInt16(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadUInt16(Endianness.BigEndian)); + } + + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt16_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.ReadUInt16((Endianness)(-1))); + } + + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt16_ShouldReadBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0x01, 0xA4}; + stream.Write(bytes); + stream.Position = 0; + + const ushort expected = 420; + ushort actual = stream.ReadUInt16(Endianness.BigEndian); + + Assert.AreEqual(2, stream.Position); + Assert.AreEqual(expected, actual); + } + + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt16_ShouldReadLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0xA4, 0x01}; + stream.Write(bytes); + stream.Position = 0; + + const ushort expected = 420; + ushort actual = stream.ReadUInt16(Endianness.LittleEndian); + + Assert.AreEqual(2, stream.Position); + Assert.AreEqual(expected, actual); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.ReadUInt32.cs b/X10D.Tests/src/IO/StreamTests.ReadUInt32.cs new file mode 100644 index 0000000..6112b80 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.ReadUInt32.cs @@ -0,0 +1,72 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt32_ShouldThrowArgumentException_GivenNonReadableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.ReadUInt32()); + Assert.ThrowsException(() => stream.ReadUInt32(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadUInt32(Endianness.BigEndian)); + } + + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt32_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.ReadUInt32()); + Assert.ThrowsException(() => stream.ReadUInt32(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadUInt32(Endianness.BigEndian)); + } + + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt32_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.ReadUInt32((Endianness)(-1))); + } + + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt32_ShouldReadBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0x00, 0x00, 0x01, 0xA4}; + stream.Write(bytes); + stream.Position = 0; + + const uint expected = 420; + uint actual = stream.ReadUInt32(Endianness.BigEndian); + + Assert.AreEqual(4, stream.Position); + Assert.AreEqual(expected, actual); + } + + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt32_ShouldReadLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00}; + stream.Write(bytes); + stream.Position = 0; + + const uint expected = 420; + uint actual = stream.ReadUInt32(Endianness.LittleEndian); + + Assert.AreEqual(4, stream.Position); + Assert.AreEqual(expected, actual); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.ReadUInt64.cs b/X10D.Tests/src/IO/StreamTests.ReadUInt64.cs new file mode 100644 index 0000000..6e5a0c7 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.ReadUInt64.cs @@ -0,0 +1,72 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt64_ShouldThrowArgumentException_GivenNonReadableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.ReadUInt64()); + Assert.ThrowsException(() => stream.ReadUInt64(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadUInt64(Endianness.BigEndian)); + } + + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt64_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.ReadUInt64()); + Assert.ThrowsException(() => stream.ReadUInt64(Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.ReadUInt64(Endianness.BigEndian)); + } + + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt64_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.ReadUInt64((Endianness)(-1))); + } + + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt64_ShouldReadBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA4}; + stream.Write(bytes); + stream.Position = 0; + + const ulong expected = 420; + ulong actual = stream.ReadUInt64(Endianness.BigEndian); + + Assert.AreEqual(8, stream.Position); + Assert.AreEqual(expected, actual); + } + + [TestMethod] + [CLSCompliant(false)] + public void ReadUInt64_ShouldWriteLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + ReadOnlySpan bytes = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + stream.Write(bytes); + stream.Position = 0; + + const ulong expected = 420; + ulong actual = stream.ReadUInt64(Endianness.LittleEndian); + + Assert.AreEqual(8, stream.Position); + Assert.AreEqual(expected, actual); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.WriteDecimal.cs b/X10D.Tests/src/IO/StreamTests.WriteDecimal.cs new file mode 100644 index 0000000..1412f37 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.WriteDecimal.cs @@ -0,0 +1,77 @@ +using System.Diagnostics; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + public void WriteDecimal_ShouldThrowArgumentException_GivenNonWriteableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.Write(420.0m, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write(420.0m, Endianness.BigEndian)); + } + + [TestMethod] + public void WriteDecimal_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.Write(420.0m, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write(420.0m, Endianness.BigEndian)); + } + + [TestMethod] + public void WriteDecimal_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.Write(420.0m, (Endianness)(-1))); + Assert.ThrowsException(() => stream.Write(420.0m, (Endianness)(-1))); + } + + [TestMethod] + public void WriteDecimal_ShouldWriteBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + stream.Write(420.0m, Endianness.BigEndian); + Assert.AreEqual(16, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[16]; + ReadOnlySpan expected = stackalloc byte[] + { + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x68 + }; + int read = stream.Read(actual); + + Assert.AreEqual(16, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } + + [TestMethod] + public void WriteDecimal_ShouldWriteLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + stream.Write(420.0m, Endianness.LittleEndian); + Assert.AreEqual(16, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[16]; + ReadOnlySpan expected = stackalloc byte[] + { + 0x68, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 + }; + int read = stream.Read(actual); + + Trace.WriteLine(string.Join(", ", actual.ToArray().Select(b => $"0x{b:X2}"))); + + Assert.AreEqual(16, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.WriteDouble.cs b/X10D.Tests/src/IO/StreamTests.WriteDouble.cs new file mode 100644 index 0000000..5605830 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.WriteDouble.cs @@ -0,0 +1,68 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + public void WriteDouble_ShouldThrowArgumentException_GivenNonWriteableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.Write(420.0, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write(420.0, Endianness.BigEndian)); + } + + [TestMethod] + public void WriteDouble_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.Write(420.0, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write(420.0, Endianness.BigEndian)); + } + + [TestMethod] + public void WriteDouble_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.Write(420.0, (Endianness)(-1))); + Assert.ThrowsException(() => stream.Write(420.0, (Endianness)(-1))); + } + + [TestMethod] + public void WriteDouble_ShouldWriteBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + stream.Write(420.0, Endianness.BigEndian); + Assert.AreEqual(8, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[8]; + ReadOnlySpan expected = stackalloc byte[] {0x40, 0x7A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}; + int read = stream.Read(actual); + + Assert.AreEqual(8, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } + + [TestMethod] + public void WriteDouble_ShouldWriteLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + stream.Write(420.0, Endianness.LittleEndian); + Assert.AreEqual(8, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[8]; + ReadOnlySpan expected = stackalloc byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7A, 0x40}; + int read = stream.Read(actual); + + Assert.AreEqual(8, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.WriteInt16.cs b/X10D.Tests/src/IO/StreamTests.WriteInt16.cs new file mode 100644 index 0000000..1e0a1e9 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.WriteInt16.cs @@ -0,0 +1,68 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + public void WriteInt16_ShouldThrowArgumentException_GivenNonWriteableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.Write((short)420, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write((short)420, Endianness.BigEndian)); + } + + [TestMethod] + public void WriteInt16_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.Write((short)420, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write((short)420, Endianness.BigEndian)); + } + + [TestMethod] + public void WriteInt16_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.Write((short)420, (Endianness)(-1))); + Assert.ThrowsException(() => stream.Write((short)420, (Endianness)(-1))); + } + + [TestMethod] + public void WriteInt16_ShouldWriteBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + stream.Write((short)420, Endianness.BigEndian); + Assert.AreEqual(2, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[2]; + ReadOnlySpan expected = stackalloc byte[] {0x01, 0xA4}; + int read = stream.Read(actual); + + Assert.AreEqual(2, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } + + [TestMethod] + public void WriteInt16_ShouldWriteLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + stream.Write((short)420, Endianness.LittleEndian); + Assert.AreEqual(2, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[2]; + ReadOnlySpan expected = stackalloc byte[] {0xA4, 0x01}; + int read = stream.Read(actual); + + Assert.AreEqual(2, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.WriteInt32.cs b/X10D.Tests/src/IO/StreamTests.WriteInt32.cs new file mode 100644 index 0000000..dae3144 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.WriteInt32.cs @@ -0,0 +1,68 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + public void WriteInt32_ShouldThrowArgumentException_GivenNonWriteableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.Write(420, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write(420, Endianness.BigEndian)); + } + + [TestMethod] + public void WriteInt32_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.Write(420, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write(420, Endianness.BigEndian)); + } + + [TestMethod] + public void WriteInt32_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.Write(420, (Endianness)(-1))); + Assert.ThrowsException(() => stream.Write(420, (Endianness)(-1))); + } + + [TestMethod] + public void WriteInt32_ShouldWriteBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + stream.Write(420, Endianness.BigEndian); + Assert.AreEqual(4, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[4]; + ReadOnlySpan expected = stackalloc byte[] {0x00, 0x00, 0x01, 0xA4}; + int read = stream.Read(actual); + + Assert.AreEqual(4, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } + + [TestMethod] + public void WriteInt32_ShouldWriteLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + stream.Write(420, Endianness.LittleEndian); + Assert.AreEqual(4, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[4]; + ReadOnlySpan expected = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00}; + int read = stream.Read(actual); + + Assert.AreEqual(4, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.WriteInt64.cs b/X10D.Tests/src/IO/StreamTests.WriteInt64.cs new file mode 100644 index 0000000..0f5e6d0 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.WriteInt64.cs @@ -0,0 +1,68 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + public void WriteInt64_ShouldThrowArgumentException_GivenNonWriteableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.Write(420L, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write(420L, Endianness.BigEndian)); + } + + [TestMethod] + public void WriteInt64_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.Write(420L, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write(420L, Endianness.BigEndian)); + } + + [TestMethod] + public void WriteInt64_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.Write(420L, (Endianness)(-1))); + Assert.ThrowsException(() => stream.Write(420L, (Endianness)(-1))); + } + + [TestMethod] + public void WriteInt64_ShouldWriteBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + stream.Write(420L, Endianness.BigEndian); + Assert.AreEqual(8, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[8]; + ReadOnlySpan expected = stackalloc byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA4}; + int read = stream.Read(actual); + + Assert.AreEqual(8, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } + + [TestMethod] + public void WriteInt64_ShouldWriteLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + stream.Write(420L, Endianness.LittleEndian); + Assert.AreEqual(8, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[8]; + ReadOnlySpan expected = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + int read = stream.Read(actual); + + Assert.AreEqual(8, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.WriteSingle.cs b/X10D.Tests/src/IO/StreamTests.WriteSingle.cs new file mode 100644 index 0000000..5da14c0 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.WriteSingle.cs @@ -0,0 +1,68 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + public void WriteSingle_ShouldThrowArgumentException_GivenNonWriteableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.Write(420.0f, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write(420.0f, Endianness.BigEndian)); + } + + [TestMethod] + public void WriteSingle_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.Write(420.0f, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write(420.0f, Endianness.BigEndian)); + } + + [TestMethod] + public void WriteSingle_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.Write(420.0f, (Endianness)(-1))); + Assert.ThrowsException(() => stream.Write(420.0f, (Endianness)(-1))); + } + + [TestMethod] + public void WriteSingle_ShouldWriteBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + stream.Write(420.0f, Endianness.BigEndian); + Assert.AreEqual(4, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[4]; + ReadOnlySpan expected = stackalloc byte[] {0x43, 0xD2, 0x00, 0x00}; + int read = stream.Read(actual); + + Assert.AreEqual(4, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } + + [TestMethod] + public void WriteSingle_ShouldWriteLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + stream.Write(420.0f, Endianness.LittleEndian); + Assert.AreEqual(4, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[4]; + ReadOnlySpan expected = stackalloc byte[] {0x00, 0x00, 0xD2, 0x43}; + int read = stream.Read(actual); + + Assert.AreEqual(4, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.WriteUInt16.cs b/X10D.Tests/src/IO/StreamTests.WriteUInt16.cs new file mode 100644 index 0000000..fe73ec7 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.WriteUInt16.cs @@ -0,0 +1,73 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt16_ShouldThrowArgumentException_GivenNonWriteableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.Write((ushort)420, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write((ushort)420, Endianness.BigEndian)); + } + + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt16_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.Write((ushort)420, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write((ushort)420, Endianness.BigEndian)); + } + + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt16_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.Write((ushort)420, (Endianness)(-1))); + Assert.ThrowsException(() => stream.Write((ushort)420, (Endianness)(-1))); + } + + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt16_ShouldWriteBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + stream.Write((ushort)420, Endianness.BigEndian); + Assert.AreEqual(2, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[2]; + ReadOnlySpan expected = stackalloc byte[] {0x01, 0xA4}; + int read = stream.Read(actual); + + Assert.AreEqual(2, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } + + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt16_ShouldWriteLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + stream.Write((ushort)420, Endianness.LittleEndian); + Assert.AreEqual(2, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[2]; + ReadOnlySpan expected = stackalloc byte[] {0xA4, 0x01}; + int read = stream.Read(actual); + + Assert.AreEqual(2, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.WriteUInt32.cs b/X10D.Tests/src/IO/StreamTests.WriteUInt32.cs new file mode 100644 index 0000000..e28e946 --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.WriteUInt32.cs @@ -0,0 +1,73 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt32_ShouldThrowArgumentException_GivenNonWriteableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.Write(420U, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write(420U, Endianness.BigEndian)); + } + + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt32_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.Write(420U, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write(420U, Endianness.BigEndian)); + } + + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt32_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.Write(420U, (Endianness)(-1))); + Assert.ThrowsException(() => stream.Write(420U, (Endianness)(-1))); + } + + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt32_ShouldWriteBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + stream.Write(420U, Endianness.BigEndian); + Assert.AreEqual(4, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[4]; + ReadOnlySpan expected = stackalloc byte[] {0x00, 0x00, 0x01, 0xA4}; + int read = stream.Read(actual); + + Assert.AreEqual(4, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } + + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt32_ShouldWriteLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + stream.Write(420U, Endianness.LittleEndian); + Assert.AreEqual(4, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[4]; + ReadOnlySpan expected = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00}; + int read = stream.Read(actual); + + Assert.AreEqual(4, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.WriteUInt64.cs b/X10D.Tests/src/IO/StreamTests.WriteUInt64.cs new file mode 100644 index 0000000..ef8065b --- /dev/null +++ b/X10D.Tests/src/IO/StreamTests.WriteUInt64.cs @@ -0,0 +1,73 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using X10D.IO; + +namespace X10D.Tests.IO; + +public partial class StreamTests +{ + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt64_ShouldThrowArgumentException_GivenNonWriteableStream() + { + Stream stream = new DummyStream(); + Assert.ThrowsException(() => stream.Write(420UL, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write(420UL, Endianness.BigEndian)); + } + + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt64_ShouldThrowArgumentNullException_GivenNullStream() + { + Stream stream = null!; + Assert.ThrowsException(() => stream.Write(420UL, Endianness.LittleEndian)); + Assert.ThrowsException(() => stream.Write(420UL, Endianness.BigEndian)); + } + + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt64_ShouldThrowArgumentOutOfRangeException_GivenInvalidEndiannessValue() + { + // we don't need to enclose this stream in a using declaration, since disposing a + // null stream is meaningless. NullStream.Dispose actually does nothing, anyway. + // that - coupled with the fact that encapsulating the stream in a using declaration causes the + // analyser to trip up and think the stream is disposed by the time the local is captured in + // assertion lambda - means this line is fine as it is. please do not change. + Stream stream = Stream.Null; + Assert.ThrowsException(() => stream.Write(420UL, (Endianness)(-1))); + Assert.ThrowsException(() => stream.Write(420UL, (Endianness)(-1))); + } + + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt64_ShouldWriteBigEndian_GivenBigEndian() + { + using var stream = new MemoryStream(); + stream.Write(420UL, Endianness.BigEndian); + Assert.AreEqual(8, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[8]; + ReadOnlySpan expected = stackalloc byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xA4}; + int read = stream.Read(actual); + + Assert.AreEqual(8, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } + + [TestMethod] + [CLSCompliant(false)] + public void WriteUInt64_ShouldWriteLittleEndian_GivenLittleEndian() + { + using var stream = new MemoryStream(); + stream.Write(420UL, Endianness.LittleEndian); + Assert.AreEqual(8, stream.Position); + stream.Position = 0; + + Span actual = stackalloc byte[8]; + ReadOnlySpan expected = stackalloc byte[] {0xA4, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + int read = stream.Read(actual); + + Assert.AreEqual(8, read); + CollectionAssert.AreEqual(expected.ToArray(), actual.ToArray()); + } +} diff --git a/X10D.Tests/src/IO/StreamTests.cs b/X10D.Tests/src/IO/StreamTests.cs index 47d4e0d..ba7eb0e 100644 --- a/X10D.Tests/src/IO/StreamTests.cs +++ b/X10D.Tests/src/IO/StreamTests.cs @@ -7,7 +7,7 @@ using X10D.IO; namespace X10D.Tests.IO; [TestClass] -public class StreamTests +public partial class StreamTests { [TestMethod] public void GetHashSha1ShouldBeCorrect() @@ -99,393 +99,6 @@ public class StreamTests Stream.Null.TryWriteHash(Span.Empty, out _)); } - [TestMethod] - public void Write_ShouldThrow_GivenUndefinedEndianness() - { - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.Write(0.0f, (Endianness)(-1)); - }); - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.Write(0.0, (Endianness)(-1)); - }); - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.Write(0.0m, (Endianness)(-1)); - }); - - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.Write((short)0, (Endianness)(-1)); - }); - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.Write(0, (Endianness)(-1)); - }); - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.Write(0L, (Endianness)(-1)); - }); - - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.Write((ushort)0, (Endianness)(-1)); - }); - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.Write(0U, (Endianness)(-1)); - }); - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.Write(0UL, (Endianness)(-1)); - }); - } - - [TestMethod] - public void Read_ShouldThrow_GivenNullStream() - { - Stream? stream = null; - Assert.ThrowsException(() => stream!.ReadSingle()); - Assert.ThrowsException(() => stream!.ReadDouble()); - Assert.ThrowsException(() => stream!.ReadDecimal()); - Assert.ThrowsException(() => stream!.ReadInt16()); - Assert.ThrowsException(() => stream!.ReadInt32()); - Assert.ThrowsException(() => stream!.ReadInt64()); - Assert.ThrowsException(() => stream!.ReadUInt16()); - Assert.ThrowsException(() => stream!.ReadUInt32()); - Assert.ThrowsException(() => stream!.ReadUInt64()); - } - - [TestMethod] - public void Write_ShouldThrow_GivenNullStream() - { - Stream? stream = null; - Assert.ThrowsException(() => stream!.Write(0.0f, Endianness.LittleEndian)); - Assert.ThrowsException(() => stream!.Write(0.0, Endianness.LittleEndian)); - Assert.ThrowsException(() => stream!.Write(0.0m, Endianness.LittleEndian)); - Assert.ThrowsException(() => stream!.Write((short)0)); - Assert.ThrowsException(() => stream!.Write(0)); - Assert.ThrowsException(() => stream!.Write(0L)); - Assert.ThrowsException(() => stream!.Write((ushort)0)); - Assert.ThrowsException(() => stream!.Write(0U)); - Assert.ThrowsException(() => stream!.Write(0UL)); - } - - [TestMethod] - public void Read_ShouldThrow_GivenUndefinedEndianness() - { - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.ReadSingle((Endianness)(-1)); - }); - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.ReadDouble((Endianness)(-1)); - }); - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.ReadDecimal((Endianness)(-1)); - }); - - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.ReadInt16((Endianness)(-1)); - }); - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.ReadInt32((Endianness)(-1)); - }); - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.ReadInt64((Endianness)(-1)); - }); - - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.ReadUInt16((Endianness)(-1)); - }); - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.ReadUInt32((Endianness)(-1)); - }); - Assert.ThrowsException(() => - { - using var stream = new MemoryStream(); - return stream.ReadUInt64((Endianness)(-1)); - }); - } - - [TestMethod] - public void WriteDouble_ShouldWriteBigEndian_GivenBigEndian() - { - using var stream = new MemoryStream(); - stream.Write(420.0, Endianness.BigEndian); - Assert.AreEqual(8, stream.Position); - stream.Position = 0; - - Span actual = stackalloc byte[8]; - ReadOnlySpan expected = stackalloc byte[] {0x40, 0x7A, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00}; - int read = stream.Read(actual); - - byte[] actualArray = actual.ToArray(); - byte[] expectedArray = expected.ToArray(); - - string actualBytes = string.Join(", ", actualArray.Select(b => $"0x{b:X2}")); - string expectedBytes = string.Join(", ", expectedArray.Select(b => $"0x{b:X2}")); - Trace.WriteLine($"Actual bytes: {actualBytes}"); - Trace.WriteLine($"Expected bytes: {expectedBytes}"); - - Assert.AreEqual(8, read); - CollectionAssert.AreEqual(expectedArray, actualArray); - } - - [TestMethod] - public void WriteDouble_ShouldWriteLittleEndian_GivenLittleEndian() - { - using var stream = new MemoryStream(); - stream.Write(420.0, Endianness.LittleEndian); - Assert.AreEqual(8, stream.Position); - stream.Position = 0; - - Span actual = stackalloc byte[8]; - ReadOnlySpan expected = stackalloc byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7A, 0x40}; - int read = stream.Read(actual); - - byte[] actualArray = actual.ToArray(); - byte[] expectedArray = expected.ToArray(); - - string actualBytes = string.Join(", ", actualArray.Select(b => $"0x{b:X2}")); - string expectedBytes = string.Join(", ", expectedArray.Select(b => $"0x{b:X2}")); - Trace.WriteLine($"Actual bytes: {actualBytes}"); - Trace.WriteLine($"Expected bytes: {expectedBytes}"); - - Assert.AreEqual(8, read); - CollectionAssert.AreEqual(expectedArray, actualArray); - } - - [TestMethod] - public void WriteSingle_ShouldWriteBigEndian_GivenBigEndian() - { - using var stream = new MemoryStream(); - stream.Write(420.0f, Endianness.BigEndian); - Assert.AreEqual(4, stream.Position); - stream.Position = 0; - - Span actual = stackalloc byte[4]; - ReadOnlySpan expected = stackalloc byte[] {0x43, 0xD2, 0x00, 0x00}; - int read = stream.Read(actual); - - byte[] actualArray = actual.ToArray(); - byte[] expectedArray = expected.ToArray(); - - string actualBytes = string.Join(", ", actualArray.Select(b => $"0x{b:X2}")); - string expectedBytes = string.Join(", ", expectedArray.Select(b => $"0x{b:X2}")); - Trace.WriteLine($"Actual bytes: {actualBytes}"); - Trace.WriteLine($"Expected bytes: {expectedBytes}"); - - Assert.AreEqual(4, read); - CollectionAssert.AreEqual(expectedArray, actualArray); - } - - [TestMethod] - public void WriteSingle_ShouldWriteLittleEndian_GivenLittleEndian() - { - using var stream = new MemoryStream(); - stream.Write(420.0f, Endianness.LittleEndian); - Assert.AreEqual(4, stream.Position); - stream.Position = 0; - - Span actual = stackalloc byte[4]; - ReadOnlySpan expected = stackalloc byte[] {0x00, 0x00, 0xD2, 0x43}; - int read = stream.Read(actual); - - byte[] actualArray = actual.ToArray(); - byte[] expectedArray = expected.ToArray(); - - string actualBytes = string.Join(", ", actualArray.Select(b => $"0x{b:X2}")); - string expectedBytes = string.Join(", ", expectedArray.Select(b => $"0x{b:X2}")); - Trace.WriteLine($"Actual bytes: {actualBytes}"); - Trace.WriteLine($"Expected bytes: {expectedBytes}"); - - Assert.AreEqual(4, read); - CollectionAssert.AreEqual(expectedArray, actualArray); - } - - [TestMethod] - public void ReadSingle_WriteSingle_ShouldBeSymmetric() - { - using var stream = new MemoryStream(); - stream.Write(420.0f, BitConverter.IsLittleEndian ? Endianness.LittleEndian : Endianness.BigEndian); - - stream.Position = 0; - Assert.AreEqual(420.0f, stream.ReadSingle(), 1e-6f); - - stream.Position = 0; - stream.Write(420.0f, Endianness.LittleEndian); - - stream.Position = 0; - Assert.AreEqual(420.0f, stream.ReadSingle(Endianness.LittleEndian), 1e-6f); - - stream.Position = 0; - stream.Write(420.0f, Endianness.BigEndian); - - stream.Position = 0; - Assert.AreEqual(420.0f, stream.ReadSingle(Endianness.BigEndian), 1e-6f); - } - - [TestMethod] - public void ReadInt16_WriteInt16_ShouldBeSymmetric() - { - using var stream = new MemoryStream(); - stream.Write((short)420); - - stream.Position = 0; - Assert.AreEqual(420, stream.ReadInt16()); - - stream.Position = 0; - stream.Write((short)420, Endianness.LittleEndian); - - stream.Position = 0; - Assert.AreEqual(420, stream.ReadInt16(Endianness.LittleEndian)); - - stream.Position = 0; - stream.Write((short)420, Endianness.BigEndian); - - stream.Position = 0; - Assert.AreEqual(420, stream.ReadInt16(Endianness.BigEndian)); - } - - [TestMethod] - public void ReadInt32_WriteInt32_ShouldBeSymmetric() - { - using var stream = new MemoryStream(); - stream.Write(420); - - stream.Position = 0; - Assert.AreEqual(420, stream.ReadInt32()); - - stream.Position = 0; - stream.Write(420, Endianness.LittleEndian); - - stream.Position = 0; - Assert.AreEqual(420, stream.ReadInt32(Endianness.LittleEndian)); - - stream.Position = 0; - stream.Write(420, Endianness.BigEndian); - - stream.Position = 0; - Assert.AreEqual(420, stream.ReadInt32(Endianness.BigEndian)); - } - - [TestMethod] - public void ReadInt64_WriteInt64_ShouldBeSymmetric() - { - using var stream = new MemoryStream(); - stream.Write(420L); - - stream.Position = 0; - Assert.AreEqual(420L, stream.ReadInt64()); - - stream.Position = 0; - stream.Write(420L, Endianness.LittleEndian); - - stream.Position = 0; - Assert.AreEqual(420L, stream.ReadInt64(Endianness.LittleEndian)); - - stream.Position = 0; - stream.Write(420L, Endianness.BigEndian); - - stream.Position = 0; - Assert.AreEqual(420L, stream.ReadInt64(Endianness.BigEndian)); - } - - [TestMethod] - [CLSCompliant(false)] - public void ReadUInt16_WriteUInt16_ShouldBeSymmetric() - { - using var stream = new MemoryStream(); - stream.Write((ushort)420); - - stream.Position = 0; - Assert.AreEqual((ushort)420, stream.ReadUInt16()); - - stream.Position = 0; - stream.Write((ushort)420, Endianness.LittleEndian); - - stream.Position = 0; - Assert.AreEqual((ushort)420, stream.ReadUInt16(Endianness.LittleEndian)); - - stream.Position = 0; - stream.Write((ushort)420, Endianness.BigEndian); - - stream.Position = 0; - Assert.AreEqual((ushort)420, stream.ReadUInt16(Endianness.BigEndian)); - } - - [TestMethod] - [CLSCompliant(false)] - public void ReadUInt32_WriteUInt32_ShouldBeSymmetric() - { - using var stream = new MemoryStream(); - stream.Write(420U); - - stream.Position = 0; - Assert.AreEqual(420U, stream.ReadUInt32()); - - stream.Position = 0; - stream.Write(420U, Endianness.LittleEndian); - - stream.Position = 0; - Assert.AreEqual(420U, stream.ReadUInt32(Endianness.LittleEndian)); - - stream.Position = 0; - stream.Write(420U, Endianness.BigEndian); - - stream.Position = 0; - Assert.AreEqual(420U, stream.ReadUInt32(Endianness.BigEndian)); - } - - [TestMethod] - [CLSCompliant(false)] - public void ReadUInt64_WriteUInt64_ShouldBeSymmetric() - { - using var stream = new MemoryStream(); - stream.Write(420UL); - - stream.Position = 0; - Assert.AreEqual(420UL, stream.ReadUInt64()); - - stream.Position = 0; - stream.Write(420UL, Endianness.LittleEndian); - - stream.Position = 0; - Assert.AreEqual(420UL, stream.ReadUInt64(Endianness.LittleEndian)); - - stream.Position = 0; - stream.Write(420UL, Endianness.BigEndian); - - stream.Position = 0; - Assert.AreEqual(420UL, stream.ReadUInt64(Endianness.BigEndian)); - } - private class DummyStream : Stream { public DummyStream(bool readable = false) diff --git a/X10D/src/IO/StreamExtensions.cs b/X10D/src/IO/StreamExtensions.cs index 4202844..f5def92 100644 --- a/X10D/src/IO/StreamExtensions.cs +++ b/X10D/src/IO/StreamExtensions.cs @@ -1,4 +1,5 @@ using System.Buffers.Binary; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.InteropServices; using System.Security.Cryptography; @@ -107,6 +108,11 @@ public static class StreamExtensions } #endif + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + const int decimalSize = sizeof(decimal); const int int32Size = sizeof(int); const int partitionSize = decimalSize / int32Size; @@ -166,6 +172,11 @@ public static class StreamExtensions } #endif + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + Span buffer = stackalloc byte[sizeof(double)]; stream.Read(buffer); @@ -221,6 +232,11 @@ public static class StreamExtensions } #endif + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + Span buffer = stackalloc byte[sizeof(short)]; stream.Read(buffer); @@ -270,6 +286,11 @@ public static class StreamExtensions } #endif + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + Span buffer = stackalloc byte[sizeof(int)]; stream.Read(buffer); @@ -319,6 +340,11 @@ public static class StreamExtensions } #endif + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + Span buffer = stackalloc byte[sizeof(long)]; stream.Read(buffer); @@ -368,6 +394,11 @@ public static class StreamExtensions } #endif + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + Span buffer = stackalloc byte[sizeof(float)]; stream.Read(buffer); @@ -425,6 +456,11 @@ public static class StreamExtensions } #endif + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + Span buffer = stackalloc byte[sizeof(ushort)]; stream.Read(buffer); @@ -476,6 +512,11 @@ public static class StreamExtensions } #endif + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + Span buffer = stackalloc byte[sizeof(uint)]; stream.Read(buffer); @@ -527,6 +568,11 @@ public static class StreamExtensions } #endif + if (!stream.CanRead) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportReading); + } + Span buffer = stackalloc byte[sizeof(ulong)]; stream.Read(buffer); @@ -609,6 +655,7 @@ public static class StreamExtensions /// The stream to which the value should be written. /// The two-byte signed integer to write. /// The number of bytes written to the stream. + [ExcludeFromCodeCoverage] public static int Write(this Stream stream, short value) { return stream.Write(value, DefaultEndianness); @@ -645,6 +692,11 @@ public static class StreamExtensions } #endif + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + Span buffer = stackalloc byte[sizeof(short)]; if (endianness == Endianness.LittleEndian) @@ -666,6 +718,7 @@ public static class StreamExtensions /// The stream to which the value should be written. /// The four-byte signed integer to write. /// The number of bytes written to the stream. + [ExcludeFromCodeCoverage] public static int Write(this Stream stream, int value) { return stream.Write(value, DefaultEndianness); @@ -703,6 +756,11 @@ public static class StreamExtensions } #endif + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + Span buffer = stackalloc byte[sizeof(int)]; if (endianness == Endianness.LittleEndian) @@ -725,6 +783,7 @@ public static class StreamExtensions /// The eight-byte signed integer to write. /// The number of bytes written to the stream. /// is . + [ExcludeFromCodeCoverage] public static int Write(this Stream stream, long value) { return stream.Write(value, DefaultEndianness); @@ -762,6 +821,11 @@ public static class StreamExtensions } #endif + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + Span buffer = stackalloc byte[sizeof(long)]; if (endianness == Endianness.LittleEndian) @@ -785,6 +849,7 @@ public static class StreamExtensions /// The number of bytes written to the stream. /// is . [CLSCompliant(false)] + [ExcludeFromCodeCoverage] public static int Write(this Stream stream, ushort value) { return stream.Write(value, DefaultEndianness); @@ -823,6 +888,11 @@ public static class StreamExtensions } #endif + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + Span buffer = stackalloc byte[sizeof(ushort)]; if (endianness == Endianness.LittleEndian) @@ -846,6 +916,7 @@ public static class StreamExtensions /// The number of bytes written to the stream. /// is . [CLSCompliant(false)] + [ExcludeFromCodeCoverage] public static int Write(this Stream stream, uint value) { return stream.Write(value, DefaultEndianness); @@ -884,6 +955,11 @@ public static class StreamExtensions } #endif + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + Span buffer = stackalloc byte[sizeof(uint)]; if (endianness == Endianness.LittleEndian) @@ -907,6 +983,7 @@ public static class StreamExtensions /// The number of bytes written to the stream. /// is . [CLSCompliant(false)] + [ExcludeFromCodeCoverage] public static int Write(this Stream stream, ulong value) { return stream.Write(value, DefaultEndianness); @@ -945,6 +1022,11 @@ public static class StreamExtensions } #endif + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + Span buffer = stackalloc byte[sizeof(ulong)]; if (endianness == Endianness.LittleEndian) @@ -991,6 +1073,11 @@ public static class StreamExtensions } #endif + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + Span buffer = stackalloc byte[sizeof(float)]; if (endianness == Endianness.LittleEndian) @@ -1061,6 +1148,11 @@ public static class StreamExtensions } #endif + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + Span buffer = stackalloc byte[sizeof(double)]; if (endianness == Endianness.LittleEndian) @@ -1108,6 +1200,7 @@ public static class StreamExtensions /// The endian encoding to use. /// The number of bytes written to the stream. /// is . + [ExcludeFromCodeCoverage] public static int Write(this Stream stream, decimal value, Endianness endianness) { #if NET6_0_OR_GREATER @@ -1131,6 +1224,11 @@ public static class StreamExtensions } #endif + if (!stream.CanWrite) + { + throw new ArgumentException(ExceptionMessages.StreamDoesNotSupportWriting); + } + int[] bits = decimal.GetBits(value); long preWritePosition = stream.Position;