From 2b68ba982dd49f0b692d19278992b8f7269751a7 Mon Sep 17 00:00:00 2001 From: JustFixMe Date: Thu, 15 Aug 2024 22:00:49 +0400 Subject: [PATCH] added more tests --- Core.Tests/Base32Conversions/Decode.cs | 2 +- Core.Tests/Base32Conversions/Encode.cs | 17 ++++- Core.Tests/Base64UrlConversions/Decode.cs | 32 +++++++++ Core.Tests/Base64UrlConversions/Encode.cs | 22 ++++++ .../SystemIOStreamExtensionsTests/Populate.cs | 58 +++++++++++++++ .../PopulateAsync.cs | 72 +++++++++++++++++++ Core/Base32.cs | 2 + Core/Base64Url.cs | 2 + Core/Extensions/SystemIOStreamExtensions.cs | 6 +- 9 files changed, 206 insertions(+), 7 deletions(-) create mode 100644 Core.Tests/SystemIOStreamExtensionsTests/Populate.cs create mode 100644 Core.Tests/SystemIOStreamExtensionsTests/PopulateAsync.cs diff --git a/Core.Tests/Base32Conversions/Decode.cs b/Core.Tests/Base32Conversions/Decode.cs index 322a4bc..f629f55 100644 --- a/Core.Tests/Base32Conversions/Decode.cs +++ b/Core.Tests/Base32Conversions/Decode.cs @@ -56,7 +56,7 @@ public class Decode var actualBytesArray = Base32.Decode(testString); actualBytesArray.Should().Equal(expected); } - + [Theory] [InlineData(" ")] [InlineData("hg2515i3215")] diff --git a/Core.Tests/Base32Conversions/Encode.cs b/Core.Tests/Base32Conversions/Encode.cs index 4c037e2..d4158af 100644 --- a/Core.Tests/Base32Conversions/Encode.cs +++ b/Core.Tests/Base32Conversions/Encode.cs @@ -43,8 +43,8 @@ public class Encode { var str = Base32.Encode(testArray); str.Should().Be(expected); - } - + } + [Theory] [InlineData(new byte[] { })] [InlineData(null)] @@ -53,4 +53,17 @@ public class Encode var actualBase32 = Base32.Encode(testArray); actualBase32.Should().Be(string.Empty); } + + [Theory] + [InlineData(new byte[] { })] + [InlineData(null)] + public void WhenCalledWithEmptyByteArray_ShouldReturnZeroAndNotChangeOutput(byte[] testArray) + { + char[] output = ['1', '2', '3', '4']; + + var charsWritten = Base32.Encode(testArray, output); + + charsWritten.Should().Be(0); + output.Should().Equal(['1', '2', '3', '4']); + } } diff --git a/Core.Tests/Base64UrlConversions/Decode.cs b/Core.Tests/Base64UrlConversions/Decode.cs index 978107f..d872e22 100644 --- a/Core.Tests/Base64UrlConversions/Decode.cs +++ b/Core.Tests/Base64UrlConversions/Decode.cs @@ -50,4 +50,36 @@ public class Decode var result = Base64Url.Decode(testString); result.Should().BeEquivalentTo(expected); } + + [Theory] + [InlineData(" ")] + [InlineData("hg2&515i3215")] + [InlineData("hg712)21")] + [InlineData("hg712f 21")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1806:Do not ignore method results", Justification = "Test case")] + public void WhenCalledWithInvalidString_ShouldThrowFormatException(string testString) + { + Action action = () => Base64Url.Decode(testString); + action.Should().Throw(); + } + + [Theory] + [InlineData("5QrdUxDUV CAEGw8pvLsEw")] + [InlineData("6nE2uKQ4$0ar9kpmybgkdw")] + [InlineData("PyD6zwDqXkG*S1HPsp41wQ")] + [InlineData("!dOlPOh3wEe9PlyQgTMt2g")] + [System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1806:Do not ignore method results", Justification = "Test case")] + public void WhenCalledWithInvalidGuidString_ShouldThrowFormatException(string testString) + { + Action action = () => Base64Url.DecodeGuid(testString); + action.Should().Throw(); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void WhenCalledWithNullString_ShouldReturnEmptyArray(string testString) + { + Base64Url.Decode(testString).Should().BeEmpty(); + } } diff --git a/Core.Tests/Base64UrlConversions/Encode.cs b/Core.Tests/Base64UrlConversions/Encode.cs index a11dfda..4a56122 100644 --- a/Core.Tests/Base64UrlConversions/Encode.cs +++ b/Core.Tests/Base64UrlConversions/Encode.cs @@ -29,4 +29,26 @@ public class Encode var result = Base64Url.Encode(testBytes); result.Should().Be(expected); } + + [Theory] + [InlineData(new byte[] { })] + [InlineData(null)] + public void WhenCalledWithEmptyByteArray_ShouldReturnEmptyString(byte[] testArray) + { + var actualBase32 = Base64Url.Encode(testArray); + actualBase32.Should().Be(string.Empty); + } + + [Theory] + [InlineData(new byte[] { })] + [InlineData(null)] + public void WhenCalledWithEmptyByteArray_ShouldReturnZeroAndNotChangeOutput(byte[] testArray) + { + char[] output = ['1', '2', '3', '4']; + + var charsWritten = Base64Url.Encode(testArray, output); + + charsWritten.Should().Be(0); + output.Should().Equal(['1', '2', '3', '4']); + } } diff --git a/Core.Tests/SystemIOStreamExtensionsTests/Populate.cs b/Core.Tests/SystemIOStreamExtensionsTests/Populate.cs new file mode 100644 index 0000000..875a643 --- /dev/null +++ b/Core.Tests/SystemIOStreamExtensionsTests/Populate.cs @@ -0,0 +1,58 @@ +using Just.Core.Extensions; + +namespace Just.Core.Tests.SystemIOStreamExtensionsTests; + +public class Populate +{ + [Theory] + [InlineData(0, 0)] + [InlineData(0, 1)] + [InlineData(0, 3)] + [InlineData(0, 5)] + [InlineData(3, 0)] + [InlineData(3, 1)] + [InlineData(3, 5)] + [InlineData(5, 0)] + [InlineData(5, 1)] + [InlineData(5, 5)] + public void WhenCalled_ShouldPopulateSpecifiedRange(int offset, int length) + { + byte[] streamContent = [0x01, 0x02, 0x03, 0x04, 0x05,]; + using var stream = new MemoryStream(streamContent); + var buffer = new byte[10]; + + stream.Populate(buffer, offset, length); + + buffer.Skip(offset).Take(length).Should().Equal(streamContent.Take(length)); + } + + [Theory] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, }, 4)] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 4)] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 5)] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, }, 5)] + public void WhenStreamContainsSameOrGreaterAmmountOfItems_ShouldPopulateBuffer(byte[] streamContent, int bufferSize) + { + using var stream = new MemoryStream(streamContent); + var buffer = new byte[bufferSize]; + + stream.Populate(buffer); + + buffer.Should().Equal(streamContent.Take(bufferSize)); + } + + [Theory] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, }, 5)] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 6)] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 10)] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, }, 9)] + public void WhenStreamContainsLessItems_ShouldThrowEndOfStreamException(byte[] streamContent, int bufferSize) + { + using var stream = new MemoryStream(streamContent); + var buffer = new byte[bufferSize]; + + Action action = () => stream.Populate(buffer); + + action.Should().Throw(); + } +} diff --git a/Core.Tests/SystemIOStreamExtensionsTests/PopulateAsync.cs b/Core.Tests/SystemIOStreamExtensionsTests/PopulateAsync.cs new file mode 100644 index 0000000..70aa318 --- /dev/null +++ b/Core.Tests/SystemIOStreamExtensionsTests/PopulateAsync.cs @@ -0,0 +1,72 @@ +using Just.Core.Extensions; + +namespace Just.Core.Tests.SystemIOStreamExtensionsTests; + +public class PopulateAsync +{ + [Fact] + public async Task WhenCancellationRequested_ShouldThrowOperationCanceledException() + { + using var cts = new CancellationTokenSource(); + byte[] streamContent = [0x01, 0x02, 0x03, 0x04, 0x05,]; + using var stream = new MemoryStream(streamContent); + var buffer = new byte[5]; + + Func action = async () => await stream.PopulateAsync(buffer, cts.Token); + cts.Cancel(); + + await action.Should().ThrowAsync(); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(0, 1)] + [InlineData(0, 3)] + [InlineData(0, 5)] + [InlineData(3, 0)] + [InlineData(3, 1)] + [InlineData(3, 5)] + [InlineData(5, 0)] + [InlineData(5, 1)] + [InlineData(5, 5)] + public async Task WhenCalled_ShouldPopulateSpecifiedRange(int offset, int length) + { + byte[] streamContent = [0x01, 0x02, 0x03, 0x04, 0x05,]; + using var stream = new MemoryStream(streamContent); + var buffer = new byte[10]; + + await stream.PopulateAsync(buffer, offset, length); + + buffer.Skip(offset).Take(length).Should().Equal(streamContent.Take(length)); + } + + [Theory] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, }, 4)] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 4)] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 5)] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, }, 5)] + public async Task WhenStreamContainsSameOrGreaterAmmountOfItems_ShouldPopulateBuffer(byte[] streamContent, int bufferSize) + { + using var stream = new MemoryStream(streamContent); + var buffer = new byte[bufferSize]; + + await stream.PopulateAsync(buffer); + + buffer.Should().Equal(streamContent.Take(bufferSize)); + } + + [Theory] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, }, 5)] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 6)] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, }, 10)] + [InlineData(new byte[]{ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, }, 9)] + public async Task WhenStreamContainsLessItems_ShouldThrowEndOfStreamException(byte[] streamContent, int bufferSize) + { + using var stream = new MemoryStream(streamContent); + var buffer = new byte[bufferSize]; + + Func action = async () => await stream.PopulateAsync(buffer); + + await action.Should().ThrowAsync(); + } +} diff --git a/Core/Base32.cs b/Core/Base32.cs index 9c83fa1..d32de7f 100644 --- a/Core/Base32.cs +++ b/Core/Base32.cs @@ -24,6 +24,8 @@ public static class Base32 [Pure] public static int Encode(ReadOnlySpan input, Span output) { + if (input.IsEmpty) return 0; + int i = 0; ReadOnlySpan alphabet = Alphabet; for (int offset = 0; offset < input.Length;) diff --git a/Core/Base64Url.cs b/Core/Base64Url.cs index d79d2f2..e94a47d 100644 --- a/Core/Base64Url.cs +++ b/Core/Base64Url.cs @@ -95,6 +95,8 @@ public static class Base64Url [Pure] public static int Encode(ReadOnlySpan input, Span output) { + if (input.IsEmpty) return 0; + var charlen = 8 * ((input.Length + 5) / 6); Span chars = stackalloc char[charlen]; Convert.TryToBase64Chars(input, chars, out int charsWritten); diff --git a/Core/Extensions/SystemIOStreamExtensions.cs b/Core/Extensions/SystemIOStreamExtensions.cs index fc05fb8..b3869a2 100644 --- a/Core/Extensions/SystemIOStreamExtensions.cs +++ b/Core/Extensions/SystemIOStreamExtensions.cs @@ -8,7 +8,7 @@ public static class SystemIOStreamExtensions => stream.Populate(buffer.AsSpan()); public static void Populate(this Stream stream, Span buffer) { - do + while (buffer.Length > 0) { var readed = stream.Read(buffer); @@ -19,7 +19,6 @@ public static class SystemIOStreamExtensions buffer = buffer[readed..]; } - while (buffer.Length > 0); } public static async ValueTask PopulateAsync(this Stream stream, byte[] buffer, CancellationToken cancellationToken = default) @@ -28,7 +27,7 @@ public static class SystemIOStreamExtensions => await stream.PopulateAsync(buffer.AsMemory(offset, length), cancellationToken); public static async ValueTask PopulateAsync(this Stream stream, Memory buffer, CancellationToken cancellationToken = default) { - do + while (buffer.Length > 0) { cancellationToken.ThrowIfCancellationRequested(); @@ -41,6 +40,5 @@ public static class SystemIOStreamExtensions buffer = buffer[readed..]; } - while (buffer.Length > 0); } }