From 602d2eda381f858ace4a9f6771a7272a044ee36a Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Wed, 18 Oct 2017 07:09:28 -0400 Subject: [PATCH] Expose/test Span-based Convert methods (#24474) --- .../ref/System.Runtime.Extensions.cs | 4 + .../System.Runtime.Extensions.Tests.csproj | 1 + .../tests/System/Convert.netcoreapp.cs | 161 ++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 src/System.Runtime.Extensions/tests/System/Convert.netcoreapp.cs diff --git a/src/System.Runtime.Extensions/ref/System.Runtime.Extensions.cs b/src/System.Runtime.Extensions/ref/System.Runtime.Extensions.cs index e0ec10aa96ef..312c20682d4f 100644 --- a/src/System.Runtime.Extensions/ref/System.Runtime.Extensions.cs +++ b/src/System.Runtime.Extensions/ref/System.Runtime.Extensions.cs @@ -191,6 +191,7 @@ public static partial class Convert public static int ToBase64CharArray(byte[] inArray, int offsetIn, int length, char[] outArray, int offsetOut, Base64FormattingOptions options) { throw null; } public static string ToBase64String(byte[] inArray, Base64FormattingOptions options) { throw null; } public static string ToBase64String(byte[] inArray, int offset, int length, Base64FormattingOptions options) { throw null; } + public static string ToBase64String(System.ReadOnlySpan bytes, Base64FormattingOptions options = Base64FormattingOptions.None) { throw null; } public static bool ToBoolean(char value) { throw null; } public static bool ToBoolean(DateTime value) { throw null; } public static byte ToByte(DateTime value) { throw null; } @@ -620,6 +621,9 @@ public static partial class Convert public static ulong ToUInt64(uint value) { throw null; } [System.CLSCompliantAttribute(false)] public static ulong ToUInt64(ulong value) { throw null; } + public static bool TryToBase64Chars(System.ReadOnlySpan bytes, System.Span chars, out int charsWritten, Base64FormattingOptions options = Base64FormattingOptions.None) { throw null; } + public static bool TryFromBase64String(string s, System.Span bytes, out int bytesWritten) { throw null; } + public static bool TryFromBase64Chars(System.ReadOnlySpan chars, System.Span bytes, out int bytesWritten) { throw null; } } public static partial class Environment { diff --git a/src/System.Runtime.Extensions/tests/System.Runtime.Extensions.Tests.csproj b/src/System.Runtime.Extensions/tests/System.Runtime.Extensions.Tests.csproj index 3b72334f4fe6..a7edd58b6025 100644 --- a/src/System.Runtime.Extensions/tests/System.Runtime.Extensions.Tests.csproj +++ b/src/System.Runtime.Extensions/tests/System.Runtime.Extensions.Tests.csproj @@ -38,6 +38,7 @@ + diff --git a/src/System.Runtime.Extensions/tests/System/Convert.netcoreapp.cs b/src/System.Runtime.Extensions/tests/System/Convert.netcoreapp.cs new file mode 100644 index 000000000000..ec1db8cc1862 --- /dev/null +++ b/src/System.Runtime.Extensions/tests/System/Convert.netcoreapp.cs @@ -0,0 +1,161 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Linq; +using Xunit; + +namespace System.Tests +{ + public partial class ConvertTests + { + [Theory] + [InlineData(new byte[0], "")] + [InlineData(new byte[] { 5, 6, 7, 8 }, "BQYHCA==")] + public void ToBase64String_Span_ProducesExpectedOutput(byte[] input, string expected) + { + Assert.Equal(expected, Convert.ToBase64String(input.AsReadOnlySpan())); + Assert.Equal(expected, Convert.ToBase64String(input.AsReadOnlySpan(), Base64FormattingOptions.None)); + Assert.Equal(expected, Convert.ToBase64String(input.AsReadOnlySpan(), Base64FormattingOptions.InsertLineBreaks)); + } + + [Fact] + public void ToBase64String_Span_LongWithOptions_ProducesExpectedOutput() + { + byte[] input = Enumerable.Range(0, 120).Select(i => (byte)i).ToArray(); + + Assert.Equal( + "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4" + + "OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx" + + "cnN0dXZ3", + Convert.ToBase64String(input)); + + Assert.Equal( + "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4" + + "OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx" + + "cnN0dXZ3", + Convert.ToBase64String(input, Base64FormattingOptions.None)); + + Assert.Equal( + "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4\r\n" + + "OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx\r\n" + + "cnN0dXZ3", + Convert.ToBase64String(input, Base64FormattingOptions.InsertLineBreaks)); + } + + [Theory] + [InlineData((Base64FormattingOptions)(-1))] + [InlineData((Base64FormattingOptions)(2))] + public void ToBase64String_Span_InvalidOptions_Throws(Base64FormattingOptions invalidOption) + { + AssertExtensions.Throws("options", () => Convert.ToBase64String(new byte[0].AsReadOnlySpan(), invalidOption)); + } + + [Theory] + [InlineData(new byte[0], "")] + [InlineData(new byte[] { 5, 6, 7, 8 }, "BQYHCA==")] + public void TryToBase64Chars_ProducesExpectedOutput(byte[] input, string expected) + { + Span dest; + + // Just right + dest = new char[expected.Length]; + Assert.True(Convert.TryToBase64Chars(input.AsReadOnlySpan(), dest, out int charsWritten)); + Assert.Equal(expected.Length, charsWritten); + Assert.Equal(expected.ToCharArray(), dest.ToArray()); + + // Too short + if (expected.Length > 0) + { + dest = new char[expected.Length - 1]; + Assert.False(Convert.TryToBase64Chars(input.AsReadOnlySpan(), dest, out charsWritten)); + Assert.Equal(0, charsWritten); + } + + // Longer than needed + dest = new char[expected.Length + 1]; + Assert.True(Convert.TryToBase64Chars(input.AsReadOnlySpan(), dest, out charsWritten)); + Assert.Equal(expected.Length, charsWritten); + Assert.Equal(expected.ToCharArray(), dest.Slice(0, expected.Length).ToArray()); + Assert.Equal(0, dest[dest.Length - 1]); + } + + [Theory] + [InlineData((Base64FormattingOptions)(-1))] + [InlineData((Base64FormattingOptions)(2))] + public void TryToBase64Chars_InvalidOptions_Throws(Base64FormattingOptions invalidOption) + { + AssertExtensions.Throws("options", + () => Convert.TryToBase64Chars(new byte[0].AsReadOnlySpan(), new char[0].AsSpan(), out int charsWritten, invalidOption)); + } + + [Theory] + [InlineData("")] + [InlineData("BQYHCA==")] + [InlineData( + "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4\r\n" + + "OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx\r\n" + + "cnN0dXZ3")] + public void TryFromBase64String_MatchesFromBase64String(string stringInput) + { + byte[] expected = Convert.FromBase64String(stringInput); + Span dest; + + // Just the right length + dest = new byte[expected.Length]; + Assert.True(Convert.TryFromBase64String(stringInput, dest, out int bytesWritten)); + Assert.Equal(expected.Length, bytesWritten); + Assert.Equal(expected, dest.ToArray()); + + // Too short + if (expected.Length > 0) + { + dest = new byte[expected.Length - 1]; + Assert.False(Convert.TryFromBase64String(stringInput, dest, out bytesWritten)); + Assert.Equal(0, bytesWritten); + } + + // Longer than needed + dest = new byte[expected.Length + 1]; + Assert.True(Convert.TryFromBase64String(stringInput, dest, out bytesWritten)); + Assert.Equal(expected.Length, bytesWritten); + Assert.Equal(expected, dest.Slice(0, expected.Length).ToArray()); + Assert.Equal(0, dest[dest.Length - 1]); + } + + [Theory] + [InlineData("")] + [InlineData("BQYHCA==")] + [InlineData( + "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4\r\n" + + "OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3Bx\r\n" + + "cnN0dXZ3")] + public void TryFromBase64Chars_MatchesFromBase64CharArray(string stringInput) + { + char[] charArrayInput = stringInput.ToCharArray(); + byte[] expected = Convert.FromBase64CharArray(charArrayInput, 0, charArrayInput.Length); + Span dest; + + // Just the right length + dest = new byte[expected.Length]; + Assert.True(Convert.TryFromBase64Chars(charArrayInput.AsReadOnlySpan(), dest, out int bytesWritten)); + Assert.Equal(expected.Length, bytesWritten); + Assert.Equal(expected, dest.ToArray()); + + // Too short + if (expected.Length > 0) + { + dest = new byte[expected.Length - 1]; + Assert.False(Convert.TryFromBase64Chars(charArrayInput.AsReadOnlySpan(), dest, out bytesWritten)); + Assert.Equal(0, bytesWritten); + } + + // Longer than needed + dest = new byte[expected.Length + 1]; + Assert.True(Convert.TryFromBase64Chars(charArrayInput.AsReadOnlySpan(), dest, out bytesWritten)); + Assert.Equal(expected.Length, bytesWritten); + Assert.Equal(expected, dest.Slice(0, dest.Length - 1).ToArray()); + Assert.Equal(0, dest[dest.Length - 1]); + } + } +}